java调用dll或so动态库文件(c++/c)

java调用dll或so动态库文件(c++/c)

Java代码  java调用dll或so动态库文件(c++/c)
  1. public class Hello {  
  2.   
  3. public native void sayHello();  
  4.   
  5. static{  
  6.     System.loadLibrary("Hello");  
  7. }  
  8.   
  9.   
  10. public static void main(String[] args){  
  11.     Hello h = new Hello();  
  12.     h.sayHello();  
  13. }  

然后编译生成class文件,用命令javah class文件生成头文件Hello.h 

创建c++工程: 
注意: 

1>:在eclipse设置c++ build 模式:将 release 状态改为active,否则java程序调用生成的dll会报以下错误 
Exception in thread "main" java.lang.UnsatisfiedLinkError: 


2>:编译的时候如果报以下错误,解决方法就是在.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 FilesJavajdk1.6.0_10includewin32 -LD:Program FilesJavajdk1.6.0_10include -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内容: 
C++代码  java调用dll或so动态库文件(c++/c)
  1.         /* DO NOT EDIT THIS FILE - it is machine generated */  
  2. #include <jni.h>  
  3. /* Header for class Hello */  
  4.   
  5. #ifndef _Included_Hello  
  6. #define _Included_Hello  
  7. #ifdef __cplusplus  
  8. extern "C" {  
  9. #endif  
  10. /* 
  11.  * Class:     Hello 
  12.  * Method:    sayHello 
  13.  * Signature: ()V 
  14.  */  
  15.     int main() ;  
  16.       
  17.       
  18. JNIEXPORT void JNICALL Java_Hello_sayHello  
  19.   (JNIEnv *, jobject);  
  20.   
  21. #ifdef __cplusplus  
  22. }  
  23. #endif  
  24. #endif  

修改后的Hello.cpp内容: 
C++代码  java调用dll或so动态库文件(c++/c)
  1. #include <iostream>    
  2. #include "Hello.h"   
  3. using namespace std;      
  4.   
  5. int main()      
  6.      {   
  7.     return 1;  
  8.      }  
  9.   
  10.   
  11. JNIEXPORT void JNICALL Java_Hello_sayHello(JNIEnv *, jobject){  
  12.     printf("Hello world! ");  
  13.     return ;  
  14. }  

a:然后用eclipse c++插件的 make targets--build生成Hello.o 
target name 随便 
make target 随便 
命令默认就可以 
   b:将wingw/bin下的g++考到 刚才生成的Hello.o同级目录下,然后在命令行里切换到Hello.o所在的目录 
   执行命令,注意参数(我的java目录D:Program FilesJava): 
   g++ -I"D:Program FilesJavajdk1.6.0_10include"  -Wl,--add-stdcall-alias -shared -o Hello.dll Hello.o   
   
  6:运行: 
    将刚才生成的dll文件拷贝到java工程的根目录下,运行Hello.class即可 


  注意:如果测试类是在某个包下的话,例如:com.test.Hello,那我们编译class文件的时候: javac com estHello.java 
  然后: javah com.test.Hello,这样生成的头文件中的方法在被调用的时候才能找到。 
   


二: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 
   
三:命令整理: 
  以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 FilesJavajdk1.6.0_10include" -I"D:Program FilesJavajdk1.6.0_10includewin32" -o Hello.o Hello.c 
  2.2:生成dll文件 
  gcc -I"D:Program FilesJavajdk1.6.0_10include" -Wl,--add-stdcall-alias -shared -o Hello.dll Hello.o 

由于时间关系,写得比较乱,o(∩_∩)o...