猿问
下载APP

请问我该如何通过JNI在Java中调用C库函数?

如何通过JNI在Java中调用C库函数


慕粉4167745
浏览 64回答 5
5回答

烧仙草VB

调用格式如下:[DllImport("ex.dll", EntryPoint = "method")]public static extern void method(int a);其中ex.dll为C++DLL名,method为函数名, 这里的int a为C++中方法的参数转换。例:C++DLL名:Interface.dll,函数为voidCopMemFree(void *vp);调用格式为:[DllImport("Interface.dll", EntryPoint = "CopMemFree")]public static extern void CopMemFree(IntPtr vp);其实C#调用C++dll主要就是C++与C#的参数转换比较困难。

皈依舞

要在java中调用c语言的库,需要使用Java提供了JNI。举例说明在c语言中定义一个 void sayHello()函数(打印Hello World);然后在Java中调用这个函数显示Hello Word.现在分别从Java和C语言两部分说明:1. Java 部分首先定义一个HelloNative,在其中申明sayHello函数,函数要申明为Native 类型的.如下:public class HelloNative {public native void sayHello();}编译这个类,生成class文件:javac HelloWorld.java利用javah生成需要的h文件javah HelloNative生成的 h文件大概如下:/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class HelloNative */#ifndef _Included_HelloNative#define _Included_HelloNative#ifdef __cplusplusextern "C" {#endif/** Class: HelloNative* Method: sayHello* Signature: ()V*/JNIEXPORT void JNICALL Java_HelloNative_sayHello(JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif可以看一下上面自动生成的程序,程序include了jni.h,这个头文件在 $JAVA_HOME下的include文件夹下. 还可以发现生成的函数名是在之前的函数名前面加上了Java_HelloNative。2. C语言部分根据上面生成的h文件编写相应的代码实现,建立一个 HelloNative.cpp用来实现显示Hello World的函数.如下:#include <stdio.h>#include "HelloNative.h"JNIEXPORT void JNICALL Java_HelloNative_sayHello(JNIEnv *, jobject){printf("Hello World!\n");}代码编写完成之后,我们再用gcc编译成库文件,命令如下;gcc -fPIC -I/usr/lib/jvm/java-7-openjdk-i386/include -I/usr/lib/jvm/java-7-openjdk-i386/include/linux -shared -o libHelloNative.so HelloNative.cpp这样就会在当前目录下生成一个libHelloNative.so的库文件.这时需要的库已经生成,在C语言下的工作已经完成了.接下来需要在Java中编写一个程序测试一下.在程序前,需要将我们的库载入进去.载入的方法是调用Java的 System.loadLibrary("HelloNative");public class TestNative{static {try {System.loadLibrary("HelloNative");}catch(UnsatisfiedLinkError e) {System.out.println( "Cannot load hello library:\n " + e.toString() );}}public static void main(String[] args) {HelloNative test = new HelloNative();test.sayHello();}}但是再编译后,运行的时候,问题又出现了.Cannot load hello library:java.lang.UnsatisfiedLinkError: no HelloNative in java.library.pathException in thread "main" java.lang.UnsatisfiedLinkError: HelloNative.sayHello()Vat HelloNative.sayHello(Native Method)at TestNative.main(TestNative.java:13)载入库失败,但是库明明就是放在当前文件夹下的,怎么会载入失败呢?用System.getProperty("java.library.path")查看,发现java.library.path中并不u存在当前的目录.主要有以下的几个解决办法:1) 将生成的库复制到java.library.path有的路径中去,当然这样不是很好2) 设置环境变量export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ,将当前的目录加入到LD_LIBRARY_PATH中3) 设置java 的选项,将当前的目录加入到其中 .java -Djava.library.path=. $LD_LIBRARY_PATH这样之后程序就能够成功的运行了.可以看见显示的"Hello World!"了

侃侃无极

一、JAVA中所需要做的工作在JAVA程序中,首先需要在类中声明所调用的库名称,如下:在这里,库的扩展名字可以不用写出来,究竟是DLL还是SO,由系统自己判断。 还需要对将要调用的方法做本地声明,关键字为native。并且只需要声明,而不需要具体实现。如下:然后编译该JAVA程序文件,生成CLASS,再用JAVAH命令,JNI就会生成C/C++的头文件。例如程序testdll.java,内容为:用javac testdll.java编译它,会生成testdll.class。再用javah testdll,则会在当前目录下生成testdll.h文件,这个文件需要被C/C++程序调用来生成所需的库文件。二、C/C++中所需要做的工作对于已生成的.h头文件,C/C++所需要做的,就是把它的各个方法具体的实现。然后编译连接成库文件即可。再把库文件拷贝到JAVA程序的路径下面,就可以用JAVA调用C/C++所实现的功能了。接上例子。我们先看一下testdll.h文件的内容:在具体实现的时候,我们只关心两个函数原型和这里JNIEXPORT和JNICALL都是JNI的关键字,表示此函数是要被JNI调用的。而jint是以JNI为中介使JAVA的int类型与本地的int沟通的一种类型,我们可以视而不见,就当做int使用。函数的名称是JAVA_再加上java程序的package路径再加函数名组成的。参数中,我们也只需要关心在JAVA程序中存在的参数,至于JNIEnv*和jclass我们一般没有必要去碰它。好,下面我们用testdll.cpp文件具体实现这两个函数:编译连接成库文件,本例是在WINDOWS下做的,生成的是DLL文件。并且名称要与JAVA中需要调用的一致,这里就是goodluck.dll把goodluck.dll拷贝到testdll.class的目录下,java testdll运行它,就可以观察到结果了。

慕勒3428872

比如:class A{public static void main(String[] args){System.out.println("Hello world");}}class B{public static void main(String[] args){for(int i=0;i<args.length;i++)System.out.print(args[i]+" ");System.out.println();}}public class Test {public static void main(String[] args){A.main(null);B.main(new String[]{"one","two","three"});}}有的IDE,比如Eclipse,会要求你选择运行哪个main。

收到一只叮咚

在main函数中调用其中定义的变量,直接调用就可以了。public class Test{public static void main(String[] args){int data = 15; //定义的局部变量。mathod_a(data); //在静态方法中调用,你遇到的问题应该是这个吧。这里的方法必须是静态的。B b = new B();b.method_b(data);//定义一个对象,在对象的方法中调用。}public static void method_a(int num){System.out.println("method_a调用main中的变量");}}class B{method_b(int num){System.out.println("method_b调用main中的变量");}}
打开App,查看更多内容
随时随地看视频慕课网APP
我要回答