JNI 和 JNA,java和其他语言的互调

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014132659/article/details/56489375

仅工作中使用到,现查现用,理解不到位,请持怀疑态度查看本文。如有问题请联系邮件:[email protected]; 以便交流。


java调用C语言的方法:

1、JNI --- java native interface
2、JNA
3、runtime.exec() ,没有研究
4、CORBA , 没有研究

JNI和JNA是什么东西?

JNI是java和其他语言相互调用的机制,c 或者 c++写的库,java想使用,需要调用dll库,这就使用JNI或者JNA去封装库提供的API。JNA是JNI的更高封装,JNA使用很方便,JNI使用就相对麻烦,需要把dll中的每个API封装一次,封装的函数去调用dll中的API。JNA则直接声明一下dll中的API,对应工作JNA都做了,我理解就是JNI的封装本来是自己写,但是JNA都帮你做了,所有使用起来JNA方便。

深入理解,以后在研究。


为什么要用这个?

工作中需要用java调用c的dll完成一些工作。了解一些,java中框架也是用JNI封装c或者c++的库。因为底层用c或者c++实现效率高,而java应用程序的开发,框架的开发只是更多去关注逻辑的实现,不在需要自己实现类,而是学会如何使用已有的类。c和c++的工作者去想如何实现比如网络通信,等等。


1、JNI 

      JNI是Java SDK中的一部分。

      JNI编程步骤:

      参考网址: http://www.cnblogs.com/moon1992/p/5260226.html

扫描二维码关注公众号,回复: 4191517 查看本文章

      1、java代码

package com.eclipse.example;  

public class JNITest {  
    public static void main(String[] args){
		System.loadLibrary("jniTest");  
        NativeMethod nm = new NativeMethod();  
          
        int ret = nm.jniFuncTest("hello world");  
        System.out.println(ret);  
          
    }  
  
}  
  
class NativeMethod {  
    /* native 原生态方法声明  */  
    /** 
     * 函数名称: int jniFuncTest(String string) 
     *  返回值: 无 
     *   描述:  指定目录加载skyeye模块。加载模块之后才能获取设备类的信息。 
     */  
    public native int jniFuncTest(String string);   
    // native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中。  
}
      用javac命令 或者 eclipse编译代码,生成NativeMethod.class  和 JNITest.class 中间字节码文件,也是java跨平台的原因。

      用javah命令生成头文件,头文件里是声明的函数就是你自己需要在c中实现的函数,也就是需要封装dll库中的函数。

javah -classpath /d/workspace_eclipse/testjava/bin  -jni  com.eclipse.example.NativeMethod

     生成头文件:com_eclipse_example_NativeMethod.h。头文件:

/* DO NOT EDIT THIS FILE - it is machine generated */  
#include <jni.h>  
/* Header for class com_eclipse_example_NativeMethod */  
  
#ifndef _Included_com_eclipse_example_NativeMethod  
#define _Included_com_eclipse_example_NativeMethod  
#ifdef __cplusplus  
extern "C" {  
#endif  
/* 
 * Class:     com_eclipse_example_NativeMethod 
 * Method:    jniFuncTest 
 * Signature: (Ljava/lang/String;)I 
 */  
JNIEXPORT jint JNICALL Java_com_eclipse_example_NativeMethod_jniFuncTest  
  (JNIEnv *, jobject, jstring);   //c需要实现的函数。  
  
#ifdef __cplusplus  
}  
#endif  
#endif

      vs创建一个dll工程,参考地址:http://blog.csdn.net/bejustice/article/details/38294253

com_eclipse_example_NativeMethod.h 文件:

/* DO NOT EDIT THIS FILE - it is machine generated */  
#include "jni.h"  
/* Header for class com_eclipse_example_NativeMethod */  
  
#ifndef _Included_com_eclipse_example_NativeMethod  
#define _Included_com_eclipse_example_NativeMethod  
#ifdef __cplusplus  
extern "C" {  
#endif  
/* 
 * Class:     com_eclipse_example_NativeMethod 
 * Method:    jniFuncTest 
 * Signature: (Ljava/lang/String;)I 
 */  
JNIEXPORT jint JNICALL Java_com_eclipse_example_NativeMethod_jniFuncTest  
  (JNIEnv *, jobject, jstring);   //c需要实现的函数。  
  
#ifdef __cplusplus  
}  
#endif  
#endif

com_eclipse_example_NativeMethod.c 文件:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <Windows.h>
#include <direct.h>
#include <tchar.h>
#include "com_eclipse_example_NativeMethod.h"

/* 函数指针 */
typedef int (*FUNC)(char *);

static HMODULE hdll = NULL;

JNIEXPORT jint JNICALL Java_com_eclipse_example_NativeMethod_jniFuncTest
	(JNIEnv * env, jobject obj, jstring str){
		hdll = LoadLibraryEx(_T("C:\\cTest.dll"), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
		if (NULL != hdll)
		{
			FUNC func = (FUNC)GetProcAddress(hdll, "func");
			if (NULL != func)
			{
				return func(str);
			}
		}

		return 0;
}

       编译,生成库jniTest.dll。也就是再一次封装了一个库给java使用。确实有点麻烦了。
       这里的麻烦在:c的类型需要和jni提供的类型对上,基本类型还好,但是复杂类型,就比较棘手。
       生成的jniTest.dll给Java调用使用。


2、JNA

     JNA是JNI更高的封装,如何封装不清楚。

      代码:

package com.eclipse.example;

import com.sun.jna.Library;
import com.sun.jna.Native;

interface CLibrary extends Library {
    CLibrary INSTANCE = (CLibrary)Native.loadLibrary("cTest", CLibrary.class);
    
	int func(String str);   //类型,函数名,参数完全一致,声明一下c 的dll库中API就可以
}

java调用:

package com.eclipse.example;

public class JNITest {
	public static void main(String[] args){
		CLibrary.INSTANCE.func("hello");
	}
}


一些补充:
Lib dll h三者的关系:
h是声明函数
dll是实现函数,运行时需要连接的
lib是桥梁,指明h中的函数在哪个dll中, 以及函数在dll的什么位置。lib是链接时需要使用的。
vs中使用第三方库的时候,属性 --> 附加依赖项是.lib,不是.dll.
如果只是编译链接程序,那么h和lib就够用了,运行只需要dll就可以了。
http://blog.csdn.net/paddybear/article/details/44058045

Java命名规则
http://www.cnblogs.com/wengfumin/articles/2337095.html

javah命令
http://www.cnblogs.com/kissazi2/p/3298884.html

elipse导入dll
http://bbs.csdn.net/topics/390650733




猜你喜欢

转载自blog.csdn.net/u014132659/article/details/56489375