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


    源: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

  • 相关阅读:
    jmeter学习笔记(二)
    jmeter学习笔记(一)
    让IE6 IE7 IE8 IE9 IE10 IE11支持Bootstrap的解决方法
    Fiddler抓包
    76. 最小覆盖子串
    Map中getOrDefault()与数值进行比较
    阻塞非阻塞与同步异步的区别
    81. 搜索旋转排序数组 II
    49. 字母异位词分组
    48. 旋转图像
  • 原文地址:https://www.cnblogs.com/LittleTiger/p/4548694.html
Copyright © 2020-2023  润新知