Java通过JNI调用C
Java调用C有多种方式,本文介绍笔者最近的学习过程,避免今后再犯类似的错误。
首先,Java肯定是调用C的动态链接库,即通过编译器编译后的dll/so文件。
下面介绍gcc编译dll的方法。
一般情况把主函数,子函数定义,子函数声明(全局变量,宏等)分别放在不同的文件中。
我们主要对子函数编译生成可用的dll,供主函数调用。
有一个工程,里面有三个文件,分别是
#include <stdio.h> #include "test.h" int main(int argc, char *argv[]) { printf("2 + 3 = %d\n", sum(2, 3)); return 0; }
1 #include <stdio.h> 2 #include"test.h" 3 4 int sum(int a, int b) 5 { 6 return a + b; 7 }
#ifndef _TEST_H_DEVC_ #define _TEST_H_DEVC_ int sum(int a, int b); #endif
假如想在main.c中调用test.c函数的dll文件,可以编译test.c的动态链接库
在Windows平台上安装MinGW, 即可模拟Linux下的gcc的编译器。
得到test.dll文件。接着把,main.c 、test.h、test.dll 放到另一个文件夹中,编译得到
可执行文件,rs.exe。运行结果得到
下面介绍javah编译C的头文件,本文主要介绍在MyEclipse下的运行步骤。
先配置javah命令如下:
其中,需要自主配置一下三个参数
Location:是你本机的javah.exe所在的路径。 Working Directory: ${project_loc}/bin Arguments: -classpath .;./classes -d "${project_loc}" -jni ${java_type_name}
配置好后,就可以一键操作生成java所需要的头文件了。
例子如下:
工程名字:zz-testdll
1 package main; 2 3 import testdll.Sum; 4 5 public class Main { 6 static{ 7 System.loadLibrary("test"); 8 } 9 public static void main(String[] args){ 10 int rs = Sum.mSum(); 11 System.out.println(rs); 12 } 13 }
1 package testdll; 2 3 public class Sum { 4 public native static int mSum(); 5 }
选中Sum.Java文件,然后运行配置好的javah命令,即可得到上图中的testdll_Sum.h文件
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class testdll_Sum */ #ifndef _Included_testdll_Sum #define _Included_testdll_Sum #ifdef __cplusplus extern "C" { #endif /* * Class: testdll_Sum * Method: mSum * Signature: ()I */ JNIEXPORT jint JNICALL Java_testdll_Sum_mSum (JNIEnv *, jclass); #ifdef __cplusplus } #endif #endif
下面要实现testdll_Sum.h文件中的方法
(因为gcc编译器和VC++编译器的实现方式的不同,参看http://www.blogjava.net/lixf/archive/2006/01/09/25177.html)
我们需要修改生成的testdll_Sum.h中方法的名字,在函数的名字前面加一个下划线即可。
更改后的testdll_Sum.h如下:
1 /* DO NOT EDIT THIS FILE - it is machine generated */ 2 #include <jni.h> 3 /* Header for class testdll_Sum */ 4 5 #ifndef _Included_testdll_Sum 6 #define _Included_testdll_Sum 7 #ifdef __cplusplus 8 extern "C" { 9 #endif 10 /* 11 * Class: testdll_Sum 12 * Method: mSum 13 * Signature: ()I 14 */ 15 JNIEXPORT jint JNICALL _Java_testdll_Sum_mSum 16 (JNIEnv *, jclass); 17 18 #ifdef __cplusplus 19 } 20 #endif 21 #endif
实现的方法如下:
#include "testdll_Sum.h" //前两个参数(env和obj)可以忽略 JNIEXPORT jint JNICALL _Java_testdll_Sum_mSum (JNIEnv * env, jclass obj) { printf("Hello world!\n"); return 5; }
在Java的include文件夹下得到三个文件,一共5个文件供编译使用。
得到test.dll,放在Java工程的运行目录下即可。
选中Main.Java文件,run,得到。
在我写完后,得知Java通过JNA可以很方便的调用C文件,有机会学习下。
以上内容,仅供参考。