`
EJB_wawa
  • 浏览: 109044 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Java调用动态库最简便方法和最好用的组件

阅读更多
Java调用动态库最简便方法和最好用的组件
记得以前 Java 要调用C/C++写得动态库都是用的 JNI 方式,还需要自己写不少 C/C++ 代码。比如说要在Java中调用已有的动态库,如 Windows 的 user32.dll 的方法 MessageBoxA,具体步骤是 Java 中声明一个 native 方法,然后用 javah 命令生成JNI样式的头文件,再自己实现头文件中声明的方法,在实现方法中装载动态库 user32.dll,调用 MessageBoxA 方法,需要把自己写的这部分 C/C++ 代码封装成一个动态库,如Sample.dll,最后在 java  中装载 Sample.dll,然后执行其中所声明的本地方法。

可见,用老实的JNI方式,我们在调用一个已知动态库的时候还需要额外生成一个符合JNI规则的动态库作为桥梁,显得有点多余了。

下面我将引入一个开源的组件 JNative,在 http://sourceforge.net/projects/jnative 下载(我是通过在sourceforge中输入java dll搜索到的),通过它调用已有动态库中的方法就非常的方便,因为中间的JNI处理过程它都为我们做好了。JNative 现在还是 Beta1 版,期待正式版的出炉,还不知道这个版本将会有什么Bug出现。

我们下载到的 jnative 的目录中可以看到三个文件,分别是 JNative.dll,libjnative.so,JNative.jar

JNative.dll  为 Windows 平台下用的,可以拷到相应的lib加载路径,如user.dir、path、system32或windows目录下
libnative.so 为Linux平台下用的,可以拷到相应的lib加载路径,如user.dir、path目录下
JNative.jar 这个就是我们编程时候要用的

在下载的 jnative 的源代码中有示例代码,观看代码 org\xvolks\test\JNativeTester.java 就知道 jnative 是如何调用动态库方法的

如代码行 User32.messageBox(0, "Demonstrates JNative in action with many Win32 calls", "Welcome to JNative", 0);

是调用的关User32的messageBox方法,而messageBox的代码是

public   static   final   int  messageBox( int  parentHandle, String message,   
        String caption,  int  buttons)  throws  NativeException,   
        IllegalAccessException {   
    JNative n =  null ;   
     try  {   
        n =  new  JNative(DLL_NAME,  "MessageBoxA" );  // 常量DLL_NAME的值为User32.dll   
         // 构造JNative时完成装载User32.dll,并且定位MessageBoxA方法   
        n.setRetVal(Type.INT);  // 指定返回参数的类型   
         int  i =  0 ;   
        n.setParameter(i++, Type.INT,  ""  + parentHandle);   
        n.setParameter(i++, Type.STRING, message);   
        n.setParameter(i++, Type.STRING, caption);   
        n.setParameter(i++, Type.INT,  ""  + buttons);  // 指定位置上的参数类型和值   
        n.invoke();  // 调用方法   
         return  Integer.parseInt(n.getRetVal());   
    }  finally  {   
         if  (n !=  null )   
            n.dispose();  // 记得释放   
    }   
}  

上面的注释是我加上去的。
Type有一种叫做Type.PSTRUCT枚举值,对C/C++中结构的处理都考虑到了,只要用JNative的Pointer类的实例来与结构对应就行了。org\xvolks\test\SNDPTester.java中演示了如何传递C/C++中的结构相对应的Java数据类型,也就是怎么封装成一个JNative的Pointer类型。

还有在JNative中用了JDK1.5的一些特性,如枚举、静态引入等,所以在JDK1.4下是不能用的。

附:JNative 当前版本到了 1.3.2 了




--------------------------------------------------------------------------------
[版权声明]本站内文章,如未标注 [转载],均系原创或翻译之作,本人 Unmi 保留一切权利。本站原创及译作未经本人许可,不得用于商业用途及传统媒体。网络媒体可随意转载,或以此为基础进行演译,但务必以链接形式注明原始出处和作者信息,否则属于侵权行为。另对本站转载他处文章,俱有说明,如有侵权请联系本人,本人将会在第一时间删除侵权文章。及此说明,重之之重。
posted on 2006-05-18 02:09 隔叶黄莺 阅读(746) 评论(15)  编辑  收藏



Feedback
# re: Java调用动态库最简便方法和最好用的组件 2007-11-14 10:31 啥事
有没有如何获得dll传出参数的例子  回复  更多评论
  


# re: Java调用动态库最简便方法和最好用的组件 2007-11-14 12:37 隔叶黄莺
没有这么聪明,C++也没办法知道,只能按照API约定来调用传参取值,知道一个地址不标识是什么类型的  回复  更多评论
  


# re: Java调用动态库最简便方法和最好用的组件 2007-11-18 10:09 隔叶黄莺
JNative 的 getRetVal() 方法就是获取dll中函数传出的参数。  回复  更多评论
  


# re: Java调用动态库最简便方法和最好用的组件 2007-11-22 17:34 啥事
可能是我没有表述清楚,我想知道jnative如何调用dll的出参。
getRetVal()只是调用是否成功的一个返回值。如:
我们有个HNBridge.dll中有getParam(Long pDataHandle,String paramName,REF String paramValue,UINT nMaxValuseLenth) 其中REF String paramValue
是一个返回值,getRetVal()只是校验该函数调用是否成功。
java如何调用REF String paramValue。
这是我的源码
public static final Object[] getparam(long s1,String s2,long s4 ) throws NativeException,IllegalAccessException{
JNative n=null;
try{
n= new JNative("HNBridge.dll", "GetParam");
n.setRetVal(Type.INT);
// n.setMemory(0, "");
//n.set
int i=0;
Pointer s6 = new Pointer(MemoryBlockFactory.createMemoryBlock(1024));
s6.zeroMemory();
s6.setStringAt(0, "ddd");
use=new UserCall("");
// s6.setStringAt(0, "sss");
//pTar=new Pointer(MemoryBlockFactory.createMemoryBlock(36));
n.setParameter(i++, Type.LONG, ""+s1);
n.setParameter(i++, Type.STRING,s2);
// n.setParameter(i++, use.createPointer());
n.setParameter(i++, s6);
n.setParameter(i++, Type.LONG, ""+s4);
n.invoke(); // 调用方法
//System.out.println(n.getParameter(0));
// s3=s6.getAsString();
System.out.println(s6.getAsString()+"fhz");
Object [] mm=new Object[2];
mm[0]=n.getRetVal();
// mm[1]=use.getValueFromPointer();
mm[1]=s6.getAsString();
// mm[1]=s3;
//use.dispose();
return mm;

}

但总是得不到正确值
  回复  更多评论
  


# re: Java调用动态库最简便方法和最好用的组件 2007-11-22 17:40 隔叶黄莺
getRetVal()是实际的返回值  回复  更多评论
  


# re: Java调用动态库最简便方法和最好用的组件 2007-12-10 17:37 hill
为什么我用自己写的程序老是收到这样的错误
Exception in thread "main" java.lang.IllegalStateException: JNative library not loaded, sorry !
at org.xvolks.jnative.JNative.<init>(JNative.java:337)
at org.xvolks.jnative.JNative.<init>(JNative.java:269)
at test.TestJNI.main(TestJNI.java:30)
即使是用JNativeTester.java也会收到错误:
Exception in thread "main" java.lang.UnsatisfiedLinkError: org.xvolks.jnative.JNative.nLoadLibrary(Ljava/lang/String;Ljava/lang/String;Z)I
at org.xvolks.jnative.JNative.nLoadLibrary(Native Method)
at org.xvolks.jnative.JNative.<init>(JNative.java:348)
at org.xvolks.jnative.JNative.<init>(JNative.java:269)
at org.xvolks.jnative.util.User32.MessageBox(User32.java:396)
at test.JNativeTester.main(JNativeTester.java:312)
  回复  更多评论
  


# re: Java调用动态库最简便方法和最好用的组件 2007-12-10 17:42 hill
用JNativeTester.java去load “user32.dll"会出现上面的错误,但是load自己的dll却是Exception in thread "main" java.lang.UnsatisfiedLinkError: D:\Project\test\src\test\umenable.dll: Can't find dependent libraries
?难道我的dll是不能用的?  回复  更多评论
  


# re: Java调用动态库最简便方法和最好用的组件 2007-12-10 17:43 隔叶黄莺
把JNative.dll 为 Windows 平台下用的,可以拷到相应的lib加载路径,如user.dir、path、system32或windows目录下,保证你的java程序能加载到这个动态库  回复  更多评论
  


# 还是有问题 2007-12-11 12:38 hill
谢谢你的解答,现在可以load我的dll了不过问题又来了,我发现看不到dll里面的方法,即使用JNative的getDLLFileExports返回的都是(几个dll都是返回这样的)
DllCanUnloadNow
DllGetClassObject
DllRegisterServer
DllUnregisterServer
我的这些dll好像是基于com的,不多我对这些都不熟悉,咋办?  回复  更多评论
  


# re: Java调用动态库最简便方法和最好用的组件 2007-12-11 12:48 隔叶黄莺
基于Com的,有些不一样的。Com初始化过程在哪里完成的呢  回复  更多评论
  


# re: Java调用动态库最简便方法和最好用的组件 2007-12-12 10:50 hill
谢谢你的解答,我发现我这个程序用jacob(Java-Com Bridge)来做就可以了,非常简单,只要new一个ActiveXComponent,就可以调用里面的函数了  回复  更多评论
  


# re: Java调用动态库最简便方法和最好用的组件 2008-04-30 10:18 cary
我用JNative来调用DLL但是现在遇到问题是类型间的转换,DLL里的类型始终不能被JAVA认出来。那怕我在DLL里这样写:return "hello",java里:
n3.setRetVal(Type.STRING);
System.out.println(n3.getRetVal())
都不能被打印出来,不知道你有遇到过类型方面的问题吗?  回复  更多评论
  


# re: Java调用动态库最简便方法和最好用的组件 2008-04-30 10:32 隔叶黄莺
没遇到这种问题,请把你能重现问题的完整代码贴出来看看  回复  更多评论
  


# re: Java调用动态库最简便方法和最好用的组件 2008-04-30 12:51 cary
n3=new JNative("CID_test","CID_GetNum");
n3.setRetVal(Type.STRING);
System.out.println("n3=="+n3.getRetVal());
这是JAVA代码。
c++

extern "C" _declspec(dllexport) string CID_GetNum()
{
char buf[32];
string s;
int i=0;
i=SW_ReceiveCID(0,buf);
if(i!=0)
{
s += buf;
return "hello";
}
return "hello";
}
你看看我这样写有问题吗?
@隔叶黄莺
  回复  更多评论
  


# re: Java调用动态库最简便方法和最好用的组件 2008-04-30 21:06 隔叶黄莺
尽量能的话还是严谨一点吧
_declspec(dllexport) 前面是两个下划线,你少写了一个
你用 string 也该把 string.h 或 string #include 进来
SW_ReceiveCID 不存在的函数


存在两个问题
1. 你的动态库必须返回一个 c-style 字符串,如 char*,用 std 的 string,java 那边不会认成是 String,你可以中间过程用 string,最后返回的字符串要是 c-style 格式。这应该不成问题,你见过许多 windows api 就是用的这种字符串,如 LPSTR 样的

2. 你在 java 代码忘了调用 dll 的相应方法,在取返回值之前必须 n3.invoke() 一下。

重新试试吧,祝你好运
分享到:
评论
1 楼 hyint 2009-02-17  
请问一下,如果你的参数是一个回调函数指针,那你在Java怎么定义这个回调函数呢?

相关推荐

    Java调用动态库最简便方法.pdf

    ### Java调用动态库最简便方法 #### 引言 在跨语言开发中,Java调用其他语言(如C/C++)编写的动态链接库(DLL)是一种常见的需求。传统上,这种调用通常依赖于Java Native Interface (JNI),但这种方法涉及到较为...

    Java调用C++动态库

    本主题聚焦于“Java调用C++动态库”,这是一个关键的技术,它允许Java应用程序利用C++编写的高效库,比如图形处理、硬件驱动或者算法实现等。这种技术主要依赖于Java Native Interface (JNI),它是Java平台标准的一...

    java调用com组件实例

    Java调用COM组件是Java与非Java环境交互的一种方式,主要应用于Windows平台,因为COM(Component Object Model)是微软提出的一种面向对象的技术,主要用于构建Windows应用程序和服务。在Java中调用COM组件,可以...

    java调用c#样例

    标题"java调用c#样例"指的是使用Java语言通过Jacob库调用C#编写的动态链接库(DLL)。C# DLL通常包含.NET Framework中的方法和功能,而Java应用程序可以借助Jacob库来访问这些功能,从而实现跨语言的互操作性。 ...

    Jnative1.4_java调用动态库所需jar

    3. **文档或教程**: 虽然没有明确提及,但通常这样的库会提供使用指南或API文档,帮助开发者了解如何设置项目,如何声明本地方法,以及如何加载和调用动态库。 使用Jnative1.4的步骤大致如下: 1. **导入JNative....

    JAVA调用COM组件

    `jacob.dll`是JACOB的动态链接库,负责实现Java和COM之间的通信,而`jacob.jar`则包含Java类库,提供了Java调用COM的API。 要在Java项目中使用JACOB,你需要进行以下步骤: 1. **添加依赖**:首先,将`jacob.jar`...

    Java调用R语言的方法

    ### Java调用R语言的方法详解 #### JRI (Java/R Interface) **简介:** JRI是一种允许Java程序通过单线程方式与R进行交互的工具。它能够将R的动态库加载到Java环境中,并提供一系列Java API来实现R的功能。JRI支持...

    Java调用dll文件开源组件jar包及说明文档

    `JNative` 是一个Java库,它提供了一种简单的方法来调用C和C++编写的本地代码。它通过JNI(Java Native Interface)来实现这一功能,使得Java开发者能够方便地利用已有的C或C++代码,扩展Java的功能。 2. **JNI...

    js调用java类的方法

    本文将深入探讨如何使用JavaScript调用Java类的方法,以实现客户端和服务器端的有效沟通。 首先,理解JavaScript(JS)和Java的运行环境差异至关重要。JS主要在浏览器环境中运行,负责处理用户交互和动态内容,而...

    delphi7调用QT5动态库实现HMACSHA

    然后,你可以使用Delphi的Jedi JNI库(Java Native Interface的Delphi版本)或者第三方组件,如madPack,来创建一个接口,使得Delphi能够调用C++编写的Qt5库。 1. 创建Qt5动态库接口: 使用C++ Builder或Qt ...

    使用JACOB工具调用COM组件

    JACOB,全称为JAVA-COM Bridge,它允许Java应用程序直接调用COM(Component Object Model)组件,这些组件通常是用Visual Basic、VC++等语言编写的,并且在Windows操作系统环境下运行。JACOB利用Java本地接口(JNI)...

    Java调用C#DLL

    - C# DLL的源码,展示了如何定义公共接口和方法供Java调用。 - Java调用DLL的源码,展示了如何使用JNA或IKVM.NET等工具进行调用。 - 测试代码,用于验证Java成功调用C# DLL并执行预期功能。 要正确使用这些源码,你...

    JAVA-dll-ocx.rar_Java调用dll_dll ocx_java EdisonSmsGw.ocx_java 调用o

    1. Java调用DLL的原理和方法,包括JNI和JNA的使用。 2. 如何在Java中通过JACOB等工具与OCX控件进行交互。 3. "EdisonSmsGw.ocx"的具体应用,可能涉及到短信服务的实现。 4. 实际的Java代码示例,供学习和参考。 ...

    java调用DLL:JNative

    ### Java调用DLL:JNative概述 在Java项目中,有时候需要调用本地系统的动态链接库(DLL)来实现特定的功能。传统的做法是通过Java Native Interface (JNI)来进行调用,但这往往涉及到复杂的配置和繁琐的过程。为了...

    java调用串口文件32位和64位

    Java调用串口文件在开发过程中常常用于与硬件设备进行通信,例如读写串行端口数据。在处理这类需求时,Java社区提供了一个开源库RXTX,它允许Java程序与串行(COM)和并行(LPT)端口进行交互。RXTX库包括两个关键的...

    java调用dll和ocx的开源控件

    Java调用DLL和OCX是跨语言交互的一个重要应用场景,主要涉及到Java的本地接口(Java Native Interface,JNI)和第三方库如Jacob项目。Jacob是一个Java和COM(Component Object Model)之间桥梁的开源库,它允许Java...

    一、JAVA调用海康威视SDK实现摄像头预览

    本文将深入探讨如何使用JAVA调用海康威视SDK来实现摄像头的预览功能。海康威视作为全球领先的安防产品及解决方案提供商,提供了丰富的SDK供开发者进行二次开发,以满足各种定制化需求。 首先,我们需要了解海康威视...

    Jna调用动态库相关jar包

    标题中提到的"Jna调用动态库相关jar包"是指JNA库的两个主要组件:jna-3.5.1.jar和platform-3.5.1.jar。这两个jar文件是JNA框架的一部分,用于在Java程序中实现对本地库的调用。 1. **jna-3.5.1.jar**:这是JNA的...

    java com串口组件调用实例

    使用RXTX,可以在不编写JNI代码的情况下直接在Java中调用串口操作方法。 2. JSerialComm:另一个流行的Java串口通信库,具有简单易用的API,支持读写操作、事件监听等功能。 以下是一个简单的RXTX示例代码,展示了...

    java调用kettle所需jar包(包含oracle和mysqljar驱动).rar

    Java调用Kettle是将Java程序与Pentaho Kettle(也称为Spoon)集成的过程,Kettle是一款强大的数据转换和ETL(提取、转换、加载)工具。在这个过程中,Java代码通过调用Kettle的相关API来执行转换或作业,实现数据...

Global site tag (gtag.js) - Google Analytics