⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch05.html

📁 java2高级编程
💻 HTML
📖 第 1 页 / 共 5 页
字号:
      }      count++;    }    ArrayManipulation am= new ArrayManipulation();    am.manipulateArray(ar, am.lock);    am.displayArray();  }}#include &lt;jni.h&gt;#include &lt;iostream.h&gt;#include &quot;ArrayManipulation.h&quot;JNIEXPORT void      JNICALL Java_ArrayManipulation_manipulateArray</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087727"></A>            (JNIEnv *env, jobject jobj, jobjectArray elements, jobject lock){  jobjectArray ret;  int i,j;  jint arraysize;  int asize;  jclass cls;  jmethodID mid;  jfieldID fid;  long localArrayCopy[3][3];  long localMatrix[3]={4,4,4};  for(i=0; i&lt;3; i++) {</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087729"></A>//API Ref: <A NAME="38227"></A>jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array,                                           jsize index)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087732"></A>    <A NAME="marker-1087730"></A> <A NAME="GetObjectArrayElement function"></A>jintArray oneDim= (jintArray)env-&gt;GetObjectArrayElement(elements, i);</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087734"></A>//API Ref: <A NAME="43498"></A>jint* GetIntArrayElements(JNIEnv *env, jintArray array, jboolean                                       *iscopy)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087737"></A>    <A NAME="marker-1087735"></A> <A NAME="GetIntArrayElements"></A>jint *element=env-&gt;GetIntArrayElements(oneDim, 0);     for(j=0; j&lt;3; j++) {        localArrayCopy[i][j]= element[j];     }  }// With the C++ copy of the array, // process the array with LAPACK, BLAS, etc.  for (i=0;i&lt;3;i++) {    for (j=0; j&lt;3 ; j++) {      localArrayCopy[i][j]=        localArrayCopy[i][j]*localMatrix[i];     }  }// Create array to send back</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087739"></A>//API Ref: <A NAME="93322"></A>jintArray NewIntArray(JNIEnv *env, jsize length)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087742"></A>  <A NAME="marker-1087740"></A><A NAME="NewIntArray function"></A>jintArray row= (jintArray)env-&gt;NewIntArray(3);</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087744"></A>//API Ref: <A NAME="38608"></A>jclass GetObjectClass(JNIEnv *env, jobject obj)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087747"></A>  <A NAME="marker-1087745"></A><A NAME="GetObjectClass function"></A>ret=(jobjectArray)env-&gt;NewObjectArray(3, env-&gt;GetObjectClass(row), 0);  for(i=0;i&lt;3;i++) {    row= (jintArray)env-&gt;NewIntArray(3);</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087749"></A>//API Ref: <A NAME="19130"></A>SetIntArrayRegion(JNIEnv *env, jintArray array, jsize startelement,                               jsize length, jint *buffer)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087752"></A>   <A NAME="marker-1087750"></A> <A NAME="SetIntArrayRegion"></A>env-&gt;SetIntArrayRegion((jintArray)row,(jsize)0,3,                           (jint *)localArrayCopy[i]);    env-&gt;SetObjectArrayElement(ret,i,row);  }  cls=env-&gt;GetObjectClass(jobj);</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087754"></A>//API Ref: <A NAME="17379"></A>jmethodID GetMethodId(JNIEnv *env, jclass class,                                   const char *methodname, const char *methodsig)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087757"></A>  <A NAME="marker-1087755"></A><A NAME="GetMethodID function"></A>mid=env-&gt;GetMethodID(cls, &quot;sendArrayResults&quot;,                             &quot;([[I)V&quot;);  if (mid == 0) {    cout &lt;&lt;&quot;Can't find method sendArrayResults&quot;;    return;  }</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087759"></A>//API Ref: <A NAME="69767"></A>void ExceptionClear(JNIEnv *env)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087763"></A>  <A NAME="marker-1087760"></A><A NAME="marker-1087761"></A><A NAME="ExceptionClear function"></A>env-&gt;ExceptionClear();</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087765"></A>//API Ref: <A NAME="77166"></A>jint MonitorEnter(JNIEnv *env, jobject object)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087768"></A>  <A NAME="marker-1087766"></A><A NAME="MonitorEnter function"></A>env-&gt;MonitorEnter(lock);</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087770"></A>//API Ref: <A NAME="62276"></A>CallVoidMethod(JNIEnv *env, jobject object, jmethodId methodid,                            object arg1)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087773"></A>  <A NAME="marker-1087771"></A><A NAME="CallVoidMethod function"></A>env-&gt;CallVoidMethod(jobj, mid, ret);</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087775"></A>//API Ref: <A NAME="37395"></A>jint MonitorExit(JNIEnv *env, jobject object)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087778"></A>  <A NAME="marker-1087776"></A><A NAME="MonitorExit function"></A>env-&gt;MonitorExit(lock);</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087780"></A>//API Ref: <A NAME="97683"></A>jthrowable ExceptionOccurred(JNIEnv *env)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087783"></A> <A NAME="marker-1087781"></A> <A NAME="ExceptionOccurred function"></A>if(env-&gt;ExceptionOccurred()) {    cout &lt;&lt; &quot;error occured copying array back&quot; &lt;&lt; endl;</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087785"></A>//API Ref: <A NAME="74611"></A>void ExceptionDescribe(JNIEnv *env)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087788"></A>    <A NAME="marker-1087786"></A><A NAME="ExceptionDescribe function"></A>env-&gt;ExceptionDescribe();    env-&gt;ExceptionClear();  }</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087790"></A>//API Ref: <A NAME="87871"></A>jfieldID GetFieldID(JNIEnv *env, jclass class, const char *fieldname,                                 const char *fieldsig)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087793"></A> <A NAME="marker-1087791"></A> <A NAME="GetFieldID function"></A>fid=env-&gt;GetFieldID(cls, &quot;arraySize&quot;,  &quot;I&quot;);  if (fid == 0) {    cout &lt;&lt;&quot;Can't find field arraySize&quot;;    return;  }  asize=env-&gt;GetIntField(jobj,fid);  if(!env-&gt;ExceptionOccurred()) {    cout&lt;&lt; &quot;Java array size=&quot; &lt;&lt; asize &lt;&lt; endl;  } else {    env-&gt;ExceptionClear();  }  return;}</PRE></DIV></DIV><DIV><H4 CLASS="A"><A NAME="pgfId-1087795"></A><A NAME="91029"></A>Other Programming Issues</H4><P CLASS="Body"><A NAME="pgfId-1087796"></A>This section presents information on accessing classes, methods, and fields, and covers threading, memory, and Java virtual machine issues. </P><DIV><H5 CLASS="B"><A NAME="pgfId-1087797"></A>Language Issues</H5><P CLASS="Body"><A NAME="pgfId-1087798"></A>So far, the native method examples have covered calling standalone C and C++ functions that either return a result or modify parameters passed into the function. However, C++--like the Java programming language--uses instances of classes. If you create a class in one native method, the reference to this class does not have an equivalent class in the Java programming language. This makes it difficult to call functions on the C++ class that was first created. </P><P CLASS="Body"><A NAME="pgfId-1087799"></A>One way to handle this situation is to keep a record of the C++ class reference and pass that back to a proxy or to the calling program. To ensure the C++ class persists across native method calls, use the C++ new operator to create a reference to the C++ object on the heap. </P><P CLASS="Body"><A NAME="pgfId-1087802"></A>The following code provides a mapping between the <A NAME="marker-1087800"></A><A NAME="marker-1087801"></A>Xbase database and Java code. The Xbase database has a C++ API and uses an initialization class to perform subsequent database operations. When the class object is created, a pointer to this object is returned as a Java <EM CLASS="CODE">int</EM> value. You can use a long or larger value for machines with greater than 32 bits. </P><PRE CLASS="CODE"><A NAME="pgfId-1087803"></A>public class CallDB {  public native int initdb();  public native short opendb(String name, int ptr);  public native short GetFieldNo(String fieldname, int ptr);  static {</PRE><PRE CLASS="CODE-caption"><A NAME="pgfId-1087805"></A>//API Ref: <A NAME="80521"></A>static void loadLibrary(String libraryname)</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087806"></A>    System.loadLibrary(&quot;dbmaplib&quot;);  }  public static void main(String args[]) {    String prefix=null;    CallDB db=new CallDB();    int res=db.initdb();    if(args.length&gt;=1) {      prefix=args[0];    }    System.out.println(db.opendb(&quot;MYFILE.DBF&quot;, res));    System.out.println(db.GetFieldNo(&quot;LASTNAME&quot;, res));    System.out.println(db.GetFieldNo(&quot;FIRSTNAME&quot;, res));   }}</PRE><P CLASS="Body"><A NAME="pgfId-1087808"></A>The return result from the call to the <EM CLASS="CODE">initdb</EM><A NAME="marker-1087807"></A> native method, the <EM CLASS="CODE">int</EM> value, is passed to subsequent native method calls. The native code included in the <EM CLASS="CODE">dbmaplib.cc</EM><A NAME="marker-1087809"></A> library dereferences the Java object passed in as a parameter and retrieves the object pointer. The line <EM CLASS="CODE">xbDbf* Myfile=(xbDbf*)ptr;</EM> casts the <EM CLASS="CODE">int</EM> pointer value to be a pointer of <EM CLASS="CODE">Xbase</EM> type <EM CLASS="CODE">xbDbf</EM>. </P><PRE CLASS="CODE"><A NAME="pgfId-1087810"></A>#include &lt;jni.h&gt;#include &lt;xbase/xbase.h&gt;#include &quot;CallDB.h&quot;JNIEXPORT jint JNICALL Java_CallDB_initdb(JNIEnv *env, jobject jobj) {  xbXBase* x;  x= new xbXBase();  xbDbf* Myfile;  Myfile =new xbDbf(x);  return ((jint)Myfile);}JNIEXPORT jshort JNICALL Java_CallDB_opendb(JNIEnv *env, jobject jobj,                                             jstring dbname, jint ptr) {  xbDbf* Myfile=(xbDbf*)ptr;  return((*Myfile).OpenDatabase( &quot;MYFILE.DBF&quot;));}JNIEXPORT jshort JNICALL Java_CallDB_GetFieldNo(JNIEnv *env, jobject jobj,                                                 jstring fieldname, jint ptr) {  xbDbf* Myfile=(xbDbf*)ptr;  return((*Myfile).GetFieldNo(env-&gt;GetStringUTFChars(fieldname,0)));}</PRE></DIV><DIV><H5 CLASS="B"><A NAME="pgfId-1087811"></A>Calling Methods</H5><P CLASS="Body"><A NAME="pgfId-1087812"></A>The section on arrays highlighted some reasons for calling Java programming language methods from within native code; for example, when you need to free the result you intend to return. Other uses for calling Java native methods from within your native code are if you need to return more than one result or you just simply want to modify Java programming language values from within native code. Calling a Java programming language method from within native code involves the following three steps: </P><OL><LI CLASS="NLS"><A NAME="pgfId-1087813"></A>Retrieve a class reference </LI><LI CLASS="NL"><A NAME="pgfId-1087814"></A>Retrieve a method identifier </LI><LI CLASS="NL"><A NAME="pgfId-1087815"></A>Call the methods</LI></OL><P CLASS="Body"><A NAME="pgfId-1087817"></A><EM CLASS="Bold">1. Retrieve a Class Reference. </EM><A NAME="marker-1087816"></A>The first step is to retrieve a reference to the class that contains the methods you want to access. To retrieve a reference, you can either use the <EM CLASS="CODE">FindClass</EM> method or access the <EM CLASS="CODE">jobject</EM> or <EM CLASS="CODE">jclass</EM> argument to the native method. </P><DIV><H6 CLASS="D"><A NAME="pgfId-1087818"></A><EM CLASS="Bold">Use the </EM><EM CLASS="C-Code">FindClass</EM><EM CLASS="Bold"> method:</EM></H6><PRE CLASS="CODE"><A NAME="pgfId-1087819"></A>JNIEXPORT void JNICALL Java_ArrayHandler_returnArray(JNIEnv *env,                                                      jobject jobj){</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087820"></A>  jclass cls = (*env)-&gt;FindClass(env, &quot;ClassName&quot;);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087821"></A>}</PRE></DIV><DIV><H6 CLASS="D"><A NAME="pgfId-1087822"></A><EM CLASS="Bold">Use the </EM><EM CLASS="C-Code">jobject</EM><EM CLASS="Bold"> argument:</EM></H6><PRE CLASS="CODE"><A NAME="pgfId-1087823"></A>JNIEXPORT void JNICALL Java_ArrayHandler_returnArray(JNIEnv *env,                                                      jobject jobj){</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087824"></A>  jclass cls=(*env)-&gt;GetObjectClass(env, jobj);</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087825"></A>}</PRE></DIV><DIV><H6 CLASS="D"><A NAME="pgfId-1087826"></A>or </H6></DIV><DIV><H6 CLASS="D"><A NAME="pgfId-1087827"></A><EM CLASS="Bold">Use the </EM><EM CLASS="C-Code">jclass</EM><EM CLASS="Bold"> argument:</EM></H6><PRE CLASS="CODE"><A NAME="pgfId-1087828"></A>JNIEXPORT void JNICALL Java_ArrayHandler_returnArray(JNIEnv *env,                                                                                                            jclass jcls){</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087829"></A>  jclass cls=jcls;</PRE><PRE CLASS="CODE"><A NAME="pgfId-1087830"></A>}</PRE><P CLASS="Body"><A NAME="pgfId-1087832"></A><EM CLASS="Bold">2. Retrieve a Method Identifier. </EM><A NAME="marker-1087831"></A>Once the class has been obtained, the second step is to call the <EM CLASS="CODE">GetMethodID</EM> function to retrieve an identifier for a method you select in the class. The identifier is needed when calling the method of that class instance. Because the Java programming language supports method overloading, you also need to specify the method signature you want to call. To find out what signature your Java method uses, run the <EM CLASS="CODE">javap</EM> command as follows: </P><PRE CLASS="CODE"><A NAME="pgfId-1087836"></A><A NAME="marker-1087833"></A><A NAME="marker-1087834"></A><A NAME="marker-1087835"></A>javap -s Class</PRE><P CLASS="Body"><A NAME="pgfId-1087837"></A>The method signature used is displayed as a comment after each method declaration as shown here: </P><PRE CLASS="CODE"><A NAME="pgfId-1087838"></A>bash# javap -s ArrayHandlerCompiled from ArrayHandler.javapublic class ArrayHandler extends java.lang.Object {  java.lang.String arrayResults[];   /*   [Ljava/lang/String;   */  static {};   /*   ()V   */  public ArrayHandler();   /*   ()V   */  public void displayArray();   /*   ()V   */  public static void main(java.lang.String[]);   /*   ([Ljava/lang/String;)V   */  public native void returnArray();   /*   ()V   */  public void sendArrayResults(java.lang.String[]);   /*   ([Ljava/lang/String;)V   */}</PRE><P CLASS="Body"><A NAME="pgfId-1087839"></A>Use the <EM CLASS="CODE">GetMethodID</EM> function to call instance methods in an object instance, or use the <EM CLASS="CODE">GetStaticMethodID</EM> function to call static methods. Their argument lists are the same. </P><P CLASS="Body">

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -