仅工作中使用到,现查现用,理解不到位,请持怀疑态度查看本文。如有问题请联系邮件:[email protected]; 以便交流。
java调用C语言的方法:
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
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