J/Direct

J/Direct是调用Win32 DLL函数最简单的方式。它的主要设计目标是与Win32API打交道,但完全可用它调用其他任何API。但是,尽管这一特性非常方便,但它同时也造成了某些限制,且降低了性能(与RNI相比)。但J/Direct也有一些明显的优点。首先,除希望调用的那个DLL里的代码之外,没有必要再编写额外的非Java代码,换言之,我们不需要一个封装器或者代理/存根DLL。其次,函数自变量与标准数据类型之间实现了自动转换。若必须传递用户自定义的数据类型,那么J/Direct可能不按我们的希望工作。第三,就象下例展示的那样,它非常简单和直接。只需少数几行,这个例子便能调用Win32 API函数MessageBox(),它能弹出一个小的模态窗口,并带有一个标题、一条消息、一个可选的图标以及几个按钮。
 

public class ShowMsgBox {
  public static void main(String args[])
  throws UnsatisfiedLinkError   {
    MessageBox(0,
      "Created by the MessageBox() Win32 func",
      "Thinking in Java", 0);
  }
  /** @dll.import("USER32") */
  private static native int
  MessageBox(int hwndOwner, String text,
    String title, int fuStyle);
}

令人震惊的是,这里便是我们利用J/Direct调用Win32 DLL函数所需的全部代码。其中的关键是位于示范代码底部的MessageBox()声明之前的@dll.import引导命令。它表面上看是一条注释,但实际并非如此。它的作用是告诉编译器:引导命令下面的函数是在USER32 DLL里实现的,而且应相应地调用。我们要做的全部事情就是提供与DLL内实现的函数相符的一个原型,并调用函数。但是毋需在Java版本里手工键入需要的每一个Win32 API函数,一个Microsoft Java包会帮我们做这件事情(很快就会详细解释)。为了让这个例子正常工作,函数必须“按名称”由DLL导出。但是,也可以用@dll.import引导命令“按顺序”链接。举个例子来说,我们可指定函数在DLL里的入口位置。稍后还会具体讲述@dll.import引导命令的特性。
用非Java代码进行链接的一个重要问题就是函数参数的自动配置。正如大家看到的那样,MessageBox()的Java声明采用了两个字串自变量,但原来的C方案则采用了两个char指针。编译器会帮助我们自动转换标准数据类型,同时遵照本章后一节要讲述的规则。
最好,大家或许已注意到了main()声明中的UnsatisfiedLinkError异常。在运行期的时候,一旦链接程序不能从非Java函数里解析出符号,就会触发这一异常(事件)。这可能是由多方面的原因造成的:.dll文件未找到;不是一个有效的DLL;或者J/Direct未获您所使用的虚拟机的支持。为了使DLL能被找到,它必须位于Windows或Windows\System目录下,位于由PATH环境变量列出的一个目录中,或者位于和.class文件相同的目录。J/Direct获得了Microsoft Java编译器1.02.4213版本及更高版本的支持,也获得了Microsoft JVM 4.79.2164及更高版本的支持。为了解自己编译器的版本号,请在命令行下运行JVC,不要加任何参数。为了解JVM的版本号,请找到msjava.dll的图标,并利用右键弹出菜单观察它的属性。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索编译器
, 函数
, java调dll
, 数据类型
, 版本
, messagebox
, 封装java事件dll
, UnsatisfiedLinkError
一个
,以便于您获取更多的相关知识。

时间: 2024-09-14 21:02:31

J/Direct的相关文章

其他J/Direct特性

通过@dll.import引导命令内的修改符(标记),还可用到J/Direct的另两项特性.第一项是对OLE函数的简化访问,第二项是选择API函数的ANSI及Unicode版本. 根据约定,所有OLE函数都会返回类型为HRESULT的一个值,它是由COM定义的一个结构化整数值.若在COM那一级编写程序,并希望从一个OLE函数里返回某些不同的东西,就必须将一个特殊的指针传递给它--该指针指向函数即将在其中填充数据的那个内存区域.但在Java中,我们没有指针可用:此外,这种方法并不简练.利用J/Di

通过 C# 使用 J# 类库中的 Zip 类压缩文件和数据

数据|压缩 本文假设您熟悉 C# 和 Windows 窗体 下载本文的代码: ZipCompression.exe (150KB) 摘要 在存储文件或者通过网络发送文件时,使用 Zip 压缩可以节省空间和网络带宽.此外,还不会丢失经过 Zip 的文件夹的目录结构,这使其成为非常有用的压缩方案.C# 语言不具有任何使您可以操纵 Zip 文件的类,但是由于面向 .NET 的语言可以共享类实现,并且 J# 在 java.util.zip 命名空间中公开了类,因此您可以在 C# 代码中使用这些类.本文将

A Comparative Overview of C#中文版(四)

中文 当考虑到C++是怎么做的时候,Java是干了件好事,它简化了参数如何传递的问题.在C++中,方法[译注:C++中没有方法一说,应该称为"函数"或"成员函数"]的参数和方法调用通过传值.引用.指针[译注:例如int.int*.int&],使得代码变得不必要的复杂.C#显式传递引用,不管是方法声明时还是调用时.它大大地减少了混乱[译注:这句话应该这么理解:由于C++的语法问题,有时你并不知道你是在使用一个对象还是一个对象引用,本节后有示例],并达到了和Ja

CORBA学习总结

我们在这个附录讨论的都是从一个Java应用里调用非Java代码最基本的技术.每种技术都有自己的优缺点.但目前最主要的问题是并非所有这些特性都能在所有JVM中找到.因此,即使一个Java程序能调用位于特定平台上的固有方法,仍有可能不适用于安装了不同JVM的另一种平台. Sun公司提供的JNI具有灵活.简单(尽管它要求对JVM内核进行大量控制).功能强大以及通用于大多数JVM的优点.到本书完稿时为止,微软仍未提供对JNI的支持,而是提供了自己的J/Direct(调用Win32 DLL函数的一种简便方

比较CORBA与RMI

我们已经知道,CORBA的一项主要特性就是对RPC(远程过程调用)的支持.利用这一技术,我们的本地对象可调用位置远程对象内的方法.当然,目前已有一项固有的Java特性可以做完全相同的事情:RMI(参考第15章).尽管RMI使Java对象之间进行RPC调用成为可能,但CORBA能在用任何语言编制的对象之间进行RPC.这显然是一项很大的区别. 然而,可通过RMI调用远程.非Java代码的服务.我们需要的全部东西就是位于服务器那一端的.某种形式的封装Java对象,它将非Java代码"包裹"于

固有方法与程序片的注意事项

固有方法为我们带来了安全问题的一些考虑.若您的Java代码发出对一个固有方法的调用,就相当于将控制权传递到了虚拟机"体系"的外面.固有方法拥有对操作系统的完全访问权限! 当然,如果由自己编写固有方法,这正是我们所希望的.但这对程序片来说却是不可接受的--至少不能默许这样做.我们不想看到从因特网远程服务器下载回来的一个程序片自由自在地操作文件系统以及机器的其他敏感区域,除非特别允许它这样做. 为了用J/Direct,RNI和COM集成防止此类情况的发生,只有受到信任(委托)的Java代码

本原接口(RNI)

同J/Direct相比,RNI是一种比非Java代码复杂得多的接口:但它的功能也十分强大.RNI比J/Direct更接近于JVM,这也使我们能写出更有效的代码,能处理固有方法中的Java对象,而且能实现与JVM内部运行机制更紧密的集成. RNI在概念上类似Sun公司的JNI.考虑到这个原因,而且由于该产品尚未正式完工,所以我只在这里指出它们之间的主要差异.欲了解更详细的情况,请参考微软公司的文档. JNI和RNI之间存在几方面引人注目的差异.下面列出的是由msjavah生成的C头文件(微软提供的

编写回调函数

有些Win32 API函数要求将一个函数指针作为自己的参数使用.Windows API函数随后就可以调用自变量函数(通常是在以后发生特定的事件时).这一技术就叫作"回调函数".回调函数的例子包括窗口进程以及我们在打印过程中设置的回调(为后台打印程序提供回调函数的地址,使其能更新状态,并在必要的时候中止打印). 另一个例子是API函数EnumWindows(),它能枚举目前系统内所有顶级窗口.EnumWindows()要求获取一个函数指针作为自己的参数,然后搜索由Windows内部维护的

汇集(Marshaling)

"汇集"(Marshaling)是指将一个函数自变量从它原始的二进制形式转换成与语言无关的某种形式,再将这种通用形式转换成适合调用函数采用的二进制格式.在前面的例子中,我们调用了MessageBox()函数,并向它传递了两个字串.MessageBox()是个C函数,而且Java字串的二进制布局与C字串并不相同.但尽管如此,自变量仍获得了正确的传递.这是由于在调用C代码前,J/Direct已帮我们考虑到了将Java字串转换成C字串的问题.这种情况适合所有标准的Java类型.下面这张表格总