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

📄 ch10.htm

📁 JAVA Developing Professional JavaApplets
💻 HTM
📖 第 1 页 / 共 5 页
字号:
Listing 10.6 shows only the code that manipulates the Java structures.The entire source code for DatabaseImpl, including the ODBC calls,can be found on the CD-ROM.<HR><BLOCKQUOTE><B>Listing 10.6. Java interface functions from DatabaseImpl.c.<BR></B></BLOCKQUOTE><BLOCKQUOTE><TT>#include &lt;StubPreamble.h&gt;<BR>#include &lt;javaString.h&gt;<BR>#include &quot;Database.h&quot;<BR>#include &quot;SQLStmt.h&quot;<BR>#include &lt;stdio.h&gt;<BR>#include &lt;sql.h&gt;<BR><BR>#define MAX_WIDTH&nbsp;&nbsp;&nbsp;&nbsp; 50<BR>#define MAX_COLS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;20<BR>#define MAX_ROWS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;200<BR><BR>static SQLSMALLINT nRows, nCols;<BR>static SQLINTEGER namelen[ MAX_COLS ];<BR>static char *cols[ MAX_COLS ];<BR>static char *rows[ MAX_ROWS ][ MAX_COLS ];<BR><BR>bool_t throwDBError(char *description)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;SignalError(0, &quot;DBException&quot;,description);<BR>&nbsp;&nbsp;&nbsp;&nbsp;return FALSE;<BR>}<BR><BR>/*<BR> * Extract from local storage into the passed String array.<BR> */<BR>void getTableRow(struct HDatabase *db,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HArrayOfString*result,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;longrow)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;int col;<BR>&nbsp;&nbsp;&nbsp;&nbsp;char *st;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;for ( col = 0; col &lt; nCols; col++ )<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;st = rows[row][col];<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unhand(result)-&gt;body[col]= makeJavaString(st, strlen(st));<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}<BR><BR>/*<BR> * Perform a database lookup using the passed HSQLStmt.<BR> */<BR>void Database_query(struct HDatabase *db,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;structHSQLStmt *stmt)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;int x;<BR>&nbsp;&nbsp;&nbsp;&nbsp;HArrayOfArray *all;<BR>&nbsp;&nbsp;&nbsp;&nbsp;HString *s;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;/* Read from the database into local storage*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;if ( doQuery(db, stmt) == FALSE )<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;freeStorage();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;/* If we have data, store it in the class*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;if ( nRows != 0 &amp;&amp; nCols != 0)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Allocate therow array (1st dimension) */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;all = (HArrayOfArray*)ArrayAlloc(T_CLASS, nRows);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ( !all )<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;freeStorage();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unhand(stmt)-&gt;query= FALSE;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throwDBError(&quot;Unableto allocate result array&quot;);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Set the arrayinto the HSQLStmt class object */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unhand(stmt)-&gt;result= all;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* For each row,store the result strings */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for ( x = 0; x&lt; nRows; x++ )<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*Allocate the columns (2nd dimension) */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;all-&gt;obj-&gt;body[x]= ArrayAlloc(T_CLASS, nCols);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*Extract the data from local storage into the<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* HSQLStmt object.<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getTableRow(db,(HArrayOfString *)all-&gt;obj-&gt;body[x], x);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Set final variablesin the object to reflect the query */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unhand(stmt)-&gt;query= TRUE;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unhand(stmt)-&gt;nRows= nRows;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unhand(stmt)-&gt;nCols= nCols;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Print the resultsof the query by calling<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * allDone( HSQLStmt.toString());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s = (HString *)execute_java_dynamic_method(0,(HObject *)stmt,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;toString&quot;,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;()Ljava/lang/String;&quot;);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;execute_java_dynamic_method(0,(HObject *)stmt, &quot;allDone&quot;,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;(Ljava/lang/String;)V&quot;,s);<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;else<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unhand(stmt)-&gt;query= FALSE;<BR>}<BR><BR>/*<BR> * Create a HSQLStmt class object and pass it to the<BR> * query routine.<BR> */<BR>struct HSQLStmt *Database_sql(struct HDatabase *db,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;structHjava_lang_String *s)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;HObject *ret;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;/* Create the object by calling its constructor*/<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;ret = execute_java_constructor(0, &quot;SQLStmt&quot;,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FindClass(0, &quot;SQLStmt&quot;, TRUE),<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;(Ljava/lang/String;)&quot;,s);<BR>&nbsp;&nbsp;&nbsp;&nbsp;if ( !ret ) return NULL;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;Database_query(db, (HSQLStmt *)ret);<BR>&nbsp;&nbsp;&nbsp;&nbsp;return (HSQLStmt *)ret;<BR>}</TT></BLOCKQUOTE><HR><P>The <TT>doQuery()</TT> function merelyuses ODBC to read a sample database into the local two-dimensionalarray: rows. The storage for the array is allocated as needed,though the total possible size is limited by the constants <TT>MAX_ROWS</TT>and <TT>MAX_COLS</TT>. The <TT>doQuery()</TT>function also fills in the variables <TT>nRows</TT>and <TT>nCols</TT> to reflect thestorage allocated in the local array. Once the data has been extractedfrom the database, it's time to move it into the SQLStmt containerobject.<P>The native method <TT>Database_query()</TT>performs most of the interesting work. After making sure that<TT>doQuery()</TT> returns some data,the function first allocates a Java array to store the rows:<BLOCKQUOTE><TT>all = (HArrayOfArray *)ArrayAlloc(T_CLASS,nRows);</TT></BLOCKQUOTE><P>Unlike C, Java two-dimensional arrays are not allocated together.In Java, a two-dimensional array is actually an array of an array.The Java function <TT>ArrayAlloc()</TT>is used to make an array. The first parameter is the type of datathat the array will contain; the second parameter is the arraylength. A JHandle pointer is returned. Since this is the firstdimension of a two-dimensional array, it will contain arrays.<TT>T_CLASS</TT> represents any object,including arrays. It signals that the array contains Jhandles.<BR><P><CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%><TR VALIGN=TOP><TD><B>Note</B></TD></TR><TR VALIGN=TOP><TD><BLOCKQUOTE>The rows of a two-dimensional Java array do not have to contain the same number of columns. Some rows could even be NULL. You should be aware of this when dealing with multidimensional arrays. The database library will make sure that the number of columns is consistent throughout the array.</BLOCKQUOTE></TD></TR></TABLE></CENTER><P><P>Assuming everything allocated successfully, the JHandle is placedinto the SQLStmt class with the following line:<BLOCKQUOTE><TT>unhand(stmt)-&gt;result = all;</TT></BLOCKQUOTE><P>If there is an error, the native method will throw a DBExceptionby using the function <TT>throwDBError()</TT>.A Java function called <TT>SignalError()</TT>is used to throw the actual exception:<BLOCKQUOTE><TT>SignalError(0, &quot;DBException&quot;,description);</TT></BLOCKQUOTE><P>The first parameter is a structure called <TT>execenv</TT>.Zero is substituted to cause the current environment to be used.The next parameter is the name of the exception, and the finalparameter is the exception description. The preceding code lineis equivalent to the Java line:<BLOCKQUOTE><TT>throw new DBException(description);<BR></TT></BLOCKQUOTE><P><CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%><TR VALIGN=TOP><TD><B>Note</B></TD></TR><TR VALIGN=TOP><TD><BLOCKQUOTE>Whenever the <TT>execenv</TT> structure (or <TT>ExecEnv</TT>) is called for, you may substitute NULL or 0. This causes the Java runtime to use the current environment. The actual environment pointer is supplied to the stub methods as parameter <TT>_EE_</TT>, but it is not passed into the native implementations.</BLOCKQUOTE></TD></TR></TABLE></CENTER><P><P>An additional array is allocated for each row; this second dimensionarray has <TT>nCols</TT> members.The array will contain String objects, so <TT>T_CLASS</TT>is again passed into <TT>ArrayAlloc()</TT>.The created array is passed into <TT>getTableRow()</TT>to be filled in with the table data.<P>The <TT>getTableRow()</TT> functioncreates a Java String object for each column's data:<BLOCKQUOTE><TT>unhand(result)-&gt;body[col] = makeJavaString(st,strlen(st));</TT></BLOCKQUOTE><P>The Java function <TT>makeJavaString()</TT>takes a C <TT>char</TT> pointer andthe string length as parameters. It returns a JHandle to an equivalentJava String, then the created String is stored. There is a corollaryfunction for <TT>makeJavaString()</TT>:<BLOCKQUOTE><TT>char *makeCString(Hjava_lang_String *s);</TT></BLOCKQUOTE><P>This function converts a Java String back into a C string. Storagefor the string is allocated from the Java heap. You should keepthe pointer in a Java class variable somewhere to prevent theC string from being garbage-collected. The following is an alternativemethod:<BLOCKQUOTE><TT>char *allocCString(Hjava_lang_String*s);</TT></BLOCKQUOTE><P>This function allocates the C string from the local heap by using<TT>malloc()</TT>. You are responsiblefor freeing the resulting pointer when you are finished with it.<P>When all the rows have been created, the method tries to printthe result. Originally, I printed the results from within Java,but I wanted to show you an example of C calling Java. The callwas moved into the native library for this purpose.<H3><A NAME="CallingBackIntoJava">Calling Back Into Java</A></H3><P>Remember the discussion of method signatures? This is where theyare used. Any Java method can be invoked from C:<BLOCKQUOTE><TT>s = (HString *)execute_java_dynamic_method(0,(HObject *)stmt,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;toString&quot;,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&quot;()Ljava/lang/String;&quot;);</TT></BLOCKQUOTE><P>The function <TT>execute_java_dynamic_method()</TT>accomplishes the invocation. A JHandle to the object is passed,along with the method name and its signature. Without the correctsignature, Java can't find the method to execute. The invokedmethod can return any normal Java value. In this case, a Stringwas returned. Do you recognize the previous call? Its Java equivalentwould be the following:<BLOCKQUOTE><TT>String s = stmt.toString();</TT></BLOCKQUOTE><P>There are actually three functions for calling back into Java:<BLOCKQUOTE><TT>Hobject *<B>execute_java_constructor</B>(ExecEnv*,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char*classname,<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbs

⌨️ 快捷键说明

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