java(JNI)调用c/c++动态链接库 linux

         已经半年没有更新博客了,今天终于找到了可以写的东西,虽然这种东西写过的大神已经很多了,我只是新瓶装旧酒而已。写点自己的感悟和大家分享,也帮助自己加深记忆。

         OK~言归正传,相信很多童鞋肯定和我一样喜欢用c++处理一些算法问题,但是有时候应用是java写的,这个时候就非常希望能够在java代码里调用c++的模块了。感谢JNI的存在~

         下面,就介绍JNI的使用,以及关于c/c++动态链接库的编译问题了。

         首先,先编写一个java文件,这个文件作为调用c/c++的载体吧,例子:

         

public class Test{
     public native void hello();
     public static void main(String[] args){
         System.loadLibrary("Test");
         Test tt = new Test();
         tt.hello();
     }
}
          在这分代码里,hello方法就是之后需要用c/c++实现的方法,然后想调用只要new一个Test类就好了。

          System.loadLibrary("Test")这一行表示加载Test这个动态链接库(在linux(unix)里对应的文件就是libTest.so,如果字符串是XXX,那么文件就是libXXX.so,这个字符串很随意,不一定要和java文件的类名一致)

          然后就是编译该代码了:javac  Test.java

          再之后,还得生成相应动态链接库的头文件:javah  Test,输入完这个命令之后,当前目录下就会多出Test.h这个文件,内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Test */

#ifndef _Included_Test
#define _Included_Test
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Test
 * Method:    hello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_Test_hello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
           乱七八糟的一大堆,不用管,只要看清楚这里定义的函数就好了:

JNIEXPORT void JNICALL Java_Test_hello
  (JNIEnv *, jobject);
这个函数相当于就是Test类里的那个hello函数,将其用c/c++实现,Test类调用hello函数时调用的就是这些c/c++代码

所以,接下来就编写一个Test.c(cpp)文件,实现这个方法

#include "Test.h"
#include <cstdio>
JNIEXPORT void JNICALL Java_Test_hello
  (JNIEnv *, jobject){
  printf("Hello World\n");
  }
OK了。下面就要编译这个c/c++文件了,它的目标文件就是***.so(linux下的c/c++动态链接库,so是 shared object的缩写,共享库)

linux将c/c++源文件编译为.so文件的基本命令为

gcc -shared -fPIC -o ***.so ***.c

或 g++ -shared -fPIC -o ***.so ***.cpp

但是,因为这里有个特殊的头文件jni.h 所以直接这么弄肯定没法编译过(除非jni.h所在路径已经在环境变量里了),因此我们在编译的时候必须再增加参数,那就是关于jni需要用到的头文件所在的目录

linux下找到jni.h的方法是找到jdk的安装路径,/usr/lib/jvm 这个路径下就会有你安装的jdk,我装的是openjdk6,所以我的全部路径就是 /usr/lib/jvm/java-6-openjdk/include 以及/usr/lib/jvm/java-6-openjdk/include/linux

所以我的编译命令就是g++ -shared -fPIC -I/usr/lib/jvm/java-6-openjdk/include  -I/usr/lib/jvm/java-6-openjdk/include/linux -o Test.so Test.cpp

这样就能得到Test.so 这个共享库了,然后用 java Test 运行即可

这个时候可能会出错,因为Test在加载动态链接库的时候不知到它的路径,环境变量里有一个 LD_LIBRARY_PATH 只要将其复制为动态链接库所在路径即可(当然这么做的结果就是只能在当前shell中有效)

export   LD_LIBRARY_PATH = 动态链接库所在路径

java Test

屏幕上就会输出 hello了

…………………………………………………………

以上就是jni一个最简单的例子,能够用java调用c/c++代码了



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java可以通过Java Native Interface(JNI调用C或C++编写的动态(也就是Windows下的.dll文件,Linux下的.so文件)。以下是一些简单的步骤: 1. 编写C或C++代码并将其编译为动态文件(.dll或.so文件)。 2. 在Java中使用JNI口声明与C或C++代码中的函数对应的Java本地方法,并将其实现为Java本地方法。 3. 编译Java代码并将其打包成jar文件。 4. 将生成的动态文件放到Java程序能够访问到的目录下。 5. 运行Java程序。 以下是一个简单的示例: 1. 编写C代码 ```c #include <stdio.h> #include "jni.h" JNIEXPORT void JNICALL Java_com_example_Test_print(JNIEnv *env, jobject obj, jstring str) { const char *c_str = (*env)->GetStringUTFChars(env, str, NULL); printf("%s\n", c_str); (*env)->ReleaseStringUTFChars(env, str, c_str); } ``` 函数名必须以Java_开头,并加上Java类的完整路径和方法名。 2. 编译动态文件 假设我们已经将上述代码保存为test.c文件,可以使用以下命令将其编译为动态文件: - Windows:gcc -shared -o test.dll test.c -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" - Linux:gcc -shared -o libtest.so test.c -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" 注意:这里需要将JDK的include目录和平台相关的include目录添加到编译选项中。 3. 在Java中声明本地方法 ```java public class Test { static { System.loadLibrary("test"); // 加载动态文件 } public static native void print(String str); } ``` 4. 实现Java本地方法 ```java Test.print("Hello, world!"); // 调用本地方法 ``` 这样就可以在Java调用C代码了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值