一篇老文章,拿来用一下。
开发平台:Eclipse3.3.1.1+CDT(cdt-master-4.0.3)+MinGW(MinGW-5.1.4)
1. java调用dll的实现
1.1 环境准备
1.1.1 下载并安装cdt
http://www.eclipse.org/cdt/downloads.php
选择自己eclipse 支持的cdt插件,下载,并且通过eclipse–>software update–>find and install 安装cdt。
1.1.2 下载并安装mingw
http://sourceforge.net/project/showfiles.php?group_id=2435
点击mingw.exe,选择 下载并安装 ,然后都选中(速度可能有点慢,要有耐心),
1.1.3 环境变量配置
在系统变量或者用户变量里添加以下变量,注意路径根据实际安装的进行修改
PATH: D:\Program Files\MinGW\bin
C_INCLUDE_PATH: D:\Program Files\MinGW\include
CPLUS_INCLUDE_PATH: D:\Program Files\MinGW\include\c++\3.4.5;D:\Program Files\MinGW\include\c++\3.4.5\mingw32;D:\Program Files\MinGW\include\c++\3.4.5\backward;D:\Program Files\MinGW\include
LIBRARY_PATH: D:\Program Files\MinGW\lib
LIBRARY_PATH 这个变量最好加上,以前没有加,也可以编译出正确的dll,但是后来编译出来的dll就有问题,最后定位出来没有加LIBRARY_PATH这个变量,造成编译出来的dll不能正常运行。(评:这是发布包类库,要么复制出来,要么安装包运行环境)
如果添加完所有变量 最好重启电脑。
1.1.4 相关设置
eclipse–>Window->Preferences->C/C+±>New CDT project wizard->Makefile Project 找到 Binary Parser 把Elf Parser取消, 选中 PE Windows Parser.由于在MinGW目录下的make文件名为"mingw32-make.exe", eclipse默认的调用文件名为"make.exe",所以先将MinGW目录下文件名为"mingw32-make.exe"做个备份,然后将该文件重命名为"make.exe"
1.1.5 java工程和 c++工程
还是以经典的HelloWorld为例
public class Hello {
public native void sayHello();
static{
System.loadLibrary("Hello");
}
public static void main(String[] args){
Hello h = new Hello();
h.sayHello();
}
}
然后编译生成class文件,用命令javah class文件生成头文件Hello.h
创建c++工程:
注意:
- 在eclipse设置c++ build 模式:将 release 状态改为active,否则java程序调用生成的dll会报以下错误Exception in thread “main” java.lang.UnsatisfiedLinkError:
- 编译的时候如果报以下错误,解决方法就是在.h文件和.cpp文件里添加一个int mian()方法
**** Rebuild of configuration Debug for project HelloC++ ****
**** Internal Builder is used for build ****
g++ -O0 -g3 -Wall -c -fmessage-length=0 -oHello.o ..\Hello.cpp
..\Hello.cpp:10:2: warning: no newline at end of file
g++ -LD:\Program Files\Java\jdk1.6.0_10\include\win32 -LD:\Program Files\Java\jdk1.6.0_10\include -oHelloC++.exe Hello.o
D:/Program Files/mingw/bin/../lib/gcc/mingw32/3.4.5/../../../libmingw32.a(main.o):main.c:(.text+0xbd): undefined reference to `WinMain@16'
collect2: ld returned 1 exit status
Build error occurred, build is stopped
Time consumed: 5192 ms.
------------------------------------------------------------------------------
修改后的Hello.h内容:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Hello */
#ifndef _Included_Hello
#define _Included_Hello
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Hello
* Method: sayHello
* Signature: ()V
*/
int main() ;
JNIEXPORT void JNICALL Java_Hello_sayHello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
修改后的Hello.cpp内容:
#include <iostream>
#include "Hello.h"
using namespace std;
int main()
{
return 1;
}
JNIEXPORT void JNICALL Java_Hello_sayHello(JNIEnv *, jobject){
printf("Hello world!\n");
return ;
}
- 然后用eclipse c++插件的 make targets–build生成Hello.o
target name 随便
make target 随便
命令默认就可以 - 将wingw/bin下的g++考到 刚才生成的Hello.o同级目录下,然后在命令行里切换到Hello.o所在的目录执行命令,注意参数(我的java目录D:\Program Files\Java\):
g++ -I"D:\Program Files\Java\jdk1.6.0_10\include" -Wl,--add-stdcall-alias -shared -o Hello.dll Hello.o
1.1.6 运行
将刚才生成的dll文件拷贝到java工程的根目录下,运行Hello.class即可
注意:如果测试类是在某个包下的话,例如:com.test.Hello,那我们编译class文件的时候: javac com\test\Hello.java
然后: javah com.test.Hello,这样生成的头文件中的方法在被调用的时候才能找到。
2 java调用so( C )
java和c / c++通信都可以通过jni来实现。 在java代码中:
System.loadLibrary(“Hello”);
Hello不能写成Hello.dll或者Hello.so,它会根据系统平台自动填充,需要注意的是在unix/linux下生成.so动态库文件的时候,
需要在Hello.so前添加lib,否则找不到.so文件(libHello.so),运行的时候需要指定.so的路径:
java -Djava.library.path=/homw/user/so所在目录 -jar Hello.jar
3. 命令整理
以c为例(如果是c++,则把gcc改成g++就OK):
1:在unix/linux环境下
1.1:生成.o文件
gcc -I/usr/lib/j2sdk1.5-ibm/include -fPIC -c example.c
1.2:生成动态库.so文件
gcc -shared -WI -soname example.o -o libexample.so
2:在windows环境下
2.1:生成.o文件
gcc -c -I"D:\Program Files\Java\jdk1.6.0_10\include" -I"D:\Program Files\Java\jdk1.6.0_10\include\win32" -o Hello.o Hello.c
2.2:生成dll文件
gcc -I"D:\Program Files\Java\jdk1.6.0_10\include" -Wl,–add-stdcall-alias -shared -o Hello.dll Hello.o
由于时间关系,写得比较乱,o(∩_∩)o…