java调用C/C++写的dll(转)

时间:2022-09-09 20:09:27

源:java调用C/C++写的dll

  Java语言本身具有跨平台性,如果通过Java调用DLL的技术方便易用,使用Java开发前台界面可以更快速,也能带来跨平台性。

Java调用C/C++写好的DLL库时,由于基本数据类型不同、使用字节序列可能有差异,所以在参数传递过程中容易出现问题,DLL中可能需要做相应的转换。

使用Java调用DLL动态链接库的方案通常有三种:JNI, Jawin, Jacob. 其JNI(Java Native Interface)是Java语言本身提供的调用本地已编译的函数库的方法,本身具有跨平台性,可以在不同的机器上调用不同的本地库。Jawin和Jacob都是sourceforge.net的开源项目,都是基于JNI技术的依赖Windows的实现,使得在Windows平台下使用COM和DLL的更加方便。

    下面,我们来详细介绍一下使用JNI来实现Java与C/C++之间的调用。

 

一、  JNI简介

JNI是Java Native Interface的缩写。从Java 1.1开始,Java Native Interface(JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。

sun相关文档:http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/jniTOC.html

 

二、  简单步骤

 

第一步:

编写Java类,用该类将DLL对外提供的函数服务进行声明,其中的Java方法均声明为native,其方法签名可以自定义,不用实现函数体。一个例子如下:DllTest.java

public class DllTest

{

     static

     {

         System.loadLibrary("chat");

     }

 

     public static native int connect(int i);

     public static native String getstring(String src);

 

     public static void main(String[] args)

     {

         DllTest dllTest = new DllTest();

         System.out.println(dllTest.connect(5));

         System.out.println(dllTest.getstring("java send"));

     }

}

其中,chat为该动态库的名字,它的扩展名字可以不用写出来,究竟是DLL还是SO,由系统自己判断。在这里,定义了两个接口函数,一个是具有int型的入参和返回值的connect函数,一个是具有String字符串对象的入参和返回值的getstring函数。他们都不需要具体的实现。 

 

第二步:

用Javah工具将该Java类生成对应的.h头文件。首先,用javac DllTest.java编译成DllTest.class 文件,然后用 javah DllTest 编译出一个 DllTest.h 文件。这个DllTest.h即是C/C++动态库中的头文件,C/C++程序需要实现它。DllTest.h 的头文件内容:

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class DllTest */

 

#ifndef _Included_DllTest

#define _Included_DllTest

#ifdef __cplusplus

extern "C" {

#endif

/*

 * Class:     DllTest

 * Method:    connect

 * Signature: (I)I

 */

JNIEXPORT jint JNICALL Java_DllTest_connect

  (JNIEnv *, jclass, jint);

 

/*

 * Class:     DllTest

 * Method:    getstring

 * Signature: (Ljava/lang/String;)Ljava/lang/String;

 */

JNIEXPORT jstring JNICALL Java_DllTest_getstring

  (JNIEnv *, jclass, jstring);

 

#ifdef __cplusplus

}

#endif

#endif

这里JNIEXPORT和JNICALL都是JNI的关键字,表示此函数是要被JNI调用的。而jint、jstring是以JNI为中介使JAVA中的数据类型与C/C++中的数据类型之间的一种中间类型。Jint可以直接当做int使用,但是jstring不能和char *等同,需要做一定的转换。函数的名称是JAVA_再加上java程序的package路径再加函数名组成的。参数中,我们也只需要关心在JAVA程序中存在的参数,至于JNIEnv*和jclass我们一般没有必要去碰它。

 

第三步:

编写C/C++代码实现.h头文件中声明的函数,该C/C++代码中包含jni.h头文件。

int i = 2;

const char *teststr = "c/c++ return";

 

JNIEXPORT jint JNICALL Java_DllTest_connect

(JNIEnv *, jclass, jint j)

{

     i = i + j;

     return i;

}

 

JNIEXPORT jstring JNICALL Java_DllTest_getstring

(JNIEnv * env, jclass, jstring policy)

{

     // jstring 转换为char * (utf-8)

     const char * s1 = env->GetStringUTFChars(policy, false);

     printf("%s/n", s1);

 

     // char * (utf-8) 转换为jstring

     jstring js = env->NewStringUTF(teststr); 

     return  js;

}

然后用C/C++的编译工具编译生成char.dll动态库。把这个动态库放到第二步中的DllTest.class所在的文件夹中。

 

第四步:

用java DllTest 执行调用,你就可以看到输出结果:

7

Java send

c/c++ return