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

📄 tij0193.html

📁 学习java的经典书籍
💻 HTML
📖 第 1 页 / 共 3 页
字号:
<html><body>

<table width="100%"><tr>
<td>
<a href="http://www.bruceeckel.com/javabook.html">Bruce Eckel's Thinking in Java</a>
</td>
<td align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0192.html">Prev</a> | <a href="tij0194.html">Next</a>
</td>
</tr></table>
<hr>

<H2 ALIGN=LEFT>
J/Direct</H2>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">J/Direct
is the simplest way to call functions in a Win32 DLL. It was designed primarily
to interface with the Win32 API, but you can use it to call any other APIs. The
ease of use of this feature is counterbalanced by some limitations and reduced
performance (compared to RNI). But J/Direct has distinct advantages. First,
there is no need to write additional non-Java code, except the code in the DLL
you want to call. In other words, you do not need a wrapper or proxy/stub DLL.
Second, function arguments are automatically converted to and from standard
data types. (If you must pass user-defined data types, J/Direct might not be
the way to go.) Third, it&#8217;s simple and straightforward, as the example
below shows. In just a few lines, this example calls the Win32 API function 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>MessageBox(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which pops up a little modal window with a title, a message, an optional icon,
and a few buttons.
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#0000ff">public</font> <font color="#0000ff">class</font> ShowMsgBox {
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String args[]) 
  <font color="#0000ff">throws</font> UnsatisfiedLinkError   {
    MessageBox(0,
      "Created by the MessageBox() Win32 func",
      "Thinking in Java", 0);
  }
  <font color="#009900">/** @dll.import("USER32") */</font>
  <font color="#0000ff">private</font> <font color="#0000ff">static</font> <font color="#0000ff">native</font> <font color="#0000ff">int</font> 
  MessageBox(<font color="#0000ff">int</font> hwndOwner, String text,
    String title, <font color="#0000ff">int</font> fuStyle);
}</PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Amazingly,
this code is all you need to call a function in a Win32 DLL using J/Direct. The
key is the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>@dll.import</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
directive before the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>MessageBox(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
declaration, at the bottom of the example code. It looks like a comment, but
it&#8217;s not: it tells the compiler that the function below the directive is
implemented in the USER32 DLL, and should be called accordingly. All you must
do is supply a prototype that matches the function implementation in the DLL
and call the function. But instead of typing in the Java version of each Win32
API function that you need, a Microsoft Java package does this for you
(I&#8217;ll describe this shortly). For this example to work, the function must
be exported 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>by
name
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
by the DLL, but the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>@dll.import
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">directive
can be used to link 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>by
ordinal
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
as well, i.e., you can specify the entry position of the function in the DLL.
I&#8217;ll cover the features of the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>@dll.import
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">directive
later.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">An
important issue in the process of linking with non-Java code is the automatic
marshaling of the function parameters. As you can see, the Java declaration of 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>MessageBox(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
takes two String arguments, but the original C implementation takes two 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>char</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
pointers. The compiler automatically converts the standard data types for you,
following the rules described in a later section.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Finally,
you might have noticed the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>UnsatisfiedLinkError</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
exception in the declaration of 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>main(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
This exception occurs when the linker is unable to resolve the symbol for the
non-Java function at run-time. This happens for a number of reasons: the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>.dll</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
file was not found, it is not a valid DLL, or J/Direct is not supported by your
virtual machine. For the DLL to be found, it must be in the Windows or
Windows\System directory, in one of the directories listed in your PATH
environment variable, or in the directory where the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>.class
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">file
is located. J/Direct is supported in the Microsoft Java compiler version
1.02.4213 or above, and in the Microsoft JVM version 4.79.2164 or above. To get
the compiler version number, run JVC from the command line with no parameters.
To get the JVM version number, locate the icon for 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>msjava.dll</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and using the context menu look at its properties.
</FONT><a name="_Toc408018827"></a><P></DIV>
<A NAME="Heading598"></A><H3 ALIGN=LEFT>
The
@dll.import directive
<P><A NAME="Index3099"></A></H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>@dll.import</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
directive, your one and only way to J/Direct, is quite flexible. It has a
number of modifiers that you can use to customize the way you link to the
non-Java code. It can also be applied to some methods within a class or to a
whole class, meaning that all of the methods you declare in that class are
implemented in the same DLL. Let&#8217;s look at these features.
</FONT><P></DIV>
<A NAME="Heading599"></A><H4 ALIGN=LEFT>
Aliasing
and linking by ordinal
</H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">For
the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>@dll.import</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
directive to work as shown above, the function in the DLL must be exported by
name. However, you might want to use a different name than the original one in
the DLL (aliasing), or the function might be exported by number (i.e. by
ordinal) instead of by name. The example below declares 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>FinestraDiMessaggio(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(the Italian equivalent of &#8220;MessageBox&#8221;) as an alias to 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>MessageBox(&#160;)</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
As you can see, the syntax is pretty simple.
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#0000ff">public</font> <font color="#0000ff">class</font> Aliasing {
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String args[]) 
  <font color="#0000ff">throws</font> UnsatisfiedLinkError   {
    FinestraDiMessaggio(0,
      "Created by the MessageBox() Win32 func",
      "Thinking in Java", 0);
  }
  <font color="#009900">/** @dll.import("USER32", 
  entrypoint="MessageBox") */</font>
  <font color="#0000ff">private</font> <font color="#0000ff">static</font> <font color="#0000ff">native</font> <font color="#0000ff">int</font> 
  FinestraDiMessaggio(<font color="#0000ff">int</font> hwndOwner, String text,
    String title, <font color="#0000ff">int</font> fuStyle);
}</PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
next example shows how to link to a function in a DLL that is not exported by
name, but by its position inside of the DLL. The example assumes that there is
a DLL named MYMATH somewhere along your path, and that this DLL contains at
position 3 a function that takes two integers and gives you back the sum.
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#0000ff">public</font> <font color="#0000ff">class</font> ByOrdinal {
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String args[]) 
  <font color="#0000ff">throws</font> UnsatisfiedLinkError {
    <font color="#0000ff">int</font> j=3, k=9;
    System.out.println("Result of DLL function:"
      + Add(j,k));
  }
  <font color="#009900">/** @dll.import("MYMATH", entrypoint = "#3") */</font>
  <font color="#0000ff">private</font> <font color="#0000ff">static</font> <font color="#0000ff">native</font> <font color="#0000ff">int</font> Add(<font color="#0000ff">int</font> op1,<font color="#0000ff">int</font> op2);
}</PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
can see the only difference is the form of the 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>entrypoint</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
argument.
</FONT><P></DIV>
<A NAME="Heading600"></A><H4 ALIGN=LEFT>
Applying
@dll.import to the entire class
</H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
<A NAME="Index3100"></A></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>@dll.import</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
directive can be applied to an entire class, meaning that all of the methods in
that class are implemented in the same DLL and with the same linkage
attributes. The directive is not inherited by subclasses; for this reason, and
since functions in a DLL are by nature 
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
functions, a better design approach is to encapsulate the API functions in a
separate class, as shown here:
</FONT><P></DIV>

<font color="#990000"><PRE><font color="#009900">/** @dll.import("USER32") */</font>
<font color="#0000ff">class</font> MyUser32Access {
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">native</font> <font color="#0000ff">int</font> 
  MessageBox(<font color="#0000ff">int</font> hwndOwner, String text,
    String title, <font color="#0000ff">int</font> fuStyle);
  <font color="#0000ff">public</font> <font color="#0000ff">native</font> <font color="#0000ff">static</font> <font color="#0000ff">boolean</font> 
  MessageBeep(<font color="#0000ff">int</font> uType);
}

<font color="#0000ff">public</font> <font color="#0000ff">class</font> WholeClass {
  <font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String args[]) 
  <font color="#0000ff">throws</font> UnsatisfiedLinkError {
    MyUser32Access.MessageBeep(4);
    MyUser32Access.MessageBox(0,
      "Created by the MessageBox() Win32 func",

⌨️ 快捷键说明

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