这是我网上查到的用jni去调用dll的简单例子,但是感觉逻辑有点乱
明明是java去调用dll,现在反过来又用java生成一个dll了,然后再去调用1) 编写java程序:这里以HelloWorld为例。
代码1:
class HelloWorld {
public native void displayHelloWorld();
static {
System.loadLibrary("hello"); //要调用的dll库
}
public static void main(String[] args) {
new HelloWorld().displayHelloWorld();
}
}
2) 编译 javac HelloWorld.java 生成HelloWorld.class文件
3) 生成扩展名为h的头文件 javah HelloWorld 生成HelloWorld.h的头文件4) 编写本地方法实现和由javah命令生成的头文件里面声明的方法名相同的方法。
代码2:
1 #include "jni.h"
2 #include "HelloWorld.h"
3 //#include other headers
4 JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj)
{
printf("Hello world!\n");
return;
} //用C++实现
5) 生成动态库
这里以在Windows中为例,需要生成dll文件。在保存HelloWorldImpl.c文件夹下面,使用VC的编译器cl成。 cl -I%java_home%\include -I%java_home%\include\win32 -LD HelloWorldImp.c -Fehello.dll 注意:生成的dll文件名在选项-Fe后面配置,这里是hello,因为在HelloWorld.java文件中我们loadLibary的时候使用的名字是hello。当然这里修改之后那里也需要修改。另外需要将-I%java_home%\include -I%java_home%\include\win32参数加上,因为在第四步里面编写本地方法的时候引入了jni.h文件。 //又生成dll文件,这个就是前面加载的那个dll库文件吧
6) 运行程序 java HelloWorld就ok.所以有点乱,明明在HelloWorld.java中System.loadLibrary("hello")加载了,可是后面又通过javac,javah等操作生成个hello.dll,所以看到迷糊了,请教大侠指点迷津还有就是c++,c,c#编写的dll文件一样么,用java调用的方法是一样的么
明明是java去调用dll,现在反过来又用java生成一个dll了,然后再去调用1) 编写java程序:这里以HelloWorld为例。
代码1:
class HelloWorld {
public native void displayHelloWorld();
static {
System.loadLibrary("hello"); //要调用的dll库
}
public static void main(String[] args) {
new HelloWorld().displayHelloWorld();
}
}
2) 编译 javac HelloWorld.java 生成HelloWorld.class文件
3) 生成扩展名为h的头文件 javah HelloWorld 生成HelloWorld.h的头文件4) 编写本地方法实现和由javah命令生成的头文件里面声明的方法名相同的方法。
代码2:
1 #include "jni.h"
2 #include "HelloWorld.h"
3 //#include other headers
4 JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj)
{
printf("Hello world!\n");
return;
} //用C++实现
5) 生成动态库
这里以在Windows中为例,需要生成dll文件。在保存HelloWorldImpl.c文件夹下面,使用VC的编译器cl成。 cl -I%java_home%\include -I%java_home%\include\win32 -LD HelloWorldImp.c -Fehello.dll 注意:生成的dll文件名在选项-Fe后面配置,这里是hello,因为在HelloWorld.java文件中我们loadLibary的时候使用的名字是hello。当然这里修改之后那里也需要修改。另外需要将-I%java_home%\include -I%java_home%\include\win32参数加上,因为在第四步里面编写本地方法的时候引入了jni.h文件。 //又生成dll文件,这个就是前面加载的那个dll库文件吧
6) 运行程序 java HelloWorld就ok.所以有点乱,明明在HelloWorld.java中System.loadLibrary("hello")加载了,可是后面又通过javac,javah等操作生成个hello.dll,所以看到迷糊了,请教大侠指点迷津还有就是c++,c,c#编写的dll文件一样么,用java调用的方法是一样的么
解决方案 »
- 新手求一道题 1!+2!+3!+...+20!的值,结果数据溢出了,如何解决?
- 一个权限控制,矛盾的地方
- 三个问题,一个100分
- 我作拉个简单考试的程序,有5个类,我分成5个文件,程序有点问题,我问老师,他就显示出和以前一样的态度——“哦,我忘记看拉,过几天给
- 谁碰到过这种诡异的事情?谢谢啦!!!!!!!!!!
- 让一个JTextField只能容纳一个字符,而且只能是'0'或者'1',怎样做最方便?
- 请高手指教!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- 请问:GregorianCalendar cal = new GregorianCalendar();
- 推荐一本学习j2EE的经典书籍吧
- 如何存为*.java文件?
- 很有意思的问题,写出你的结果(Java基础牢不牢)
- 判断字符串编码格式问题
2 生成dll 无所谓了,java也可以调用编译器的,你把功能分开,一个就负责使用,一个就负责生成,各自调试。
首先应该要有hello.dll,
然后才能有System.loadLibrary("hello"),没有dll又哪来的加载呢,对吧 **
但这其中涉及到jni,所以
首先把主类写好,于是就先有System.loadLibrary("hello")
然后调用javah生成相应的头文件,然后实现该头文件中声明的方法,该方法就是主类的native void displayHelloWorld()方法的具体实现,主类并没有实现displayHelloWorld()方法对不对?
主类并没有实现displayHelloWorld()方法,要调用它必然是通过外部的连接库,那么主类是如果定位这个连接库呢,就是System.loadLibrary("hello"),上面**的地方也说了,要先有dll才有加载,所以就有LZ的第五步
5) 生成动态库dll是win系统的规范,所以没什么太大的差别,java要调用它必须要用jni,即整个过程大同小异
明明是我调用dll,现在怎么反过来我又生成一个dll啊
这两个dll是不是一个dll啊
正常不是先有dll,然后我们再写java代码去调用它的么,现在怎么又要我们去写个本地方法,再编译,再有c++去实现,再生成dll呢
真的感觉晕了
不是你生成一个dll,是你的需求需要你调用一个dll,那个dll是本来就有的,而且相应的一套东西也应该是
全的。你只负责写你那个主类就可以了。
一般来说,主类并不直接调用既存的dll,因为dll的接口类型,参数类型有可能跟java不一样,所以都是自己定义一个接口,即自己做一个dll,然后在这个dll去调用其它的dll
到底是先有鸡还是先有蛋呢,我很笨,请您指点迷津啊
还有要自己做一个dll,那么是不是还要懂c++/c啊?因为我不会在dll里再调dll
代码2:
1 #include "jni.h"
2 #include "HelloWorld.h"
3 //#include other headers
4 JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj)
{
printf("Hello world!\n");
return;
}
这段代码就是c代码
win系统的调用dll,有动态调用和静态调用
动态调用使用loadLibrary,即在上面的代码中loadLibrary(xxx.dll);然后通过函数指针指向dll的接口而调用
静态就是通过#include把dll或lib导入,跟java的import类似
你要直接调用dll,那你就要知道该dll的接口在java中的定义形式
即native void displayHelloWorld(); 改成dll的接口在java中的定义形式
我上班用不了QQ,不好意思
现在的实际问题是这样的,给我一个dll的文件,让我去用java调用
dll的名字:test.dll
里面的方法名:temp()
返回值是String类型的
我应该怎么做
剩下的什么都没有了
而jni是java的规范,要求dll的接口要符合jni规范
你从别人那里拿到的test.dll,如果接口本身符合jni规范,那你可以直接调用
如果不符合,那就只能生成个中间dll去调用如果你的test.dll符合jni规范,那直接声明public native String temp(); 然后System.loadlibry("test.dll");即可
如果不符合jni规范
那就修改例子的代码中调用你的test.dll
public native void displayHelloWorld(); 改成
public native String getTemp(); 1 #include "jni.h"
2 #include "HelloWorld.h"
3 //#include other headers
#include "test.h" //如果有头文件或者有lib,可以直接导入,如果是lib,要声明一下temp接口
4 JNIEXPORT jstring JNICALL Java_HelloWorld_getTemp(JNIEnv *env, jobject obj)
{
return temp(); //如果有头文件的话
} 如果没有头文件或lib
#include <windows.h> //here
4 JNIEXPORT jstring JNICALL Java_HelloWorld_getTemp(JNIEnv *env, jobject obj)
{
HMODULE hDllLib = LoadLibrary(_T("test.dll"));
jstring rtn;
if (hDllLib)
{
FARPROC fpTemp = GetProcAddress(hDllLib,"temp");
rtn = (*fpTemp)();
FreeLibrary(hDllLib);
} return rtn;
}