首页 > 代码库 > Java通过JNI调用C

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;}
main.c
1 #include <stdio.h>2 #include"test.h"3 4 int sum(int a, int b)5 {6     return a + b;7 }
test.c
#ifndef _TEST_H_DEVC_#define _TEST_H_DEVC_int sum(int a, int b);#endif
test.h

假如想在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}/binArguments: -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 }
Main.Java
1 package testdll;2 3 public class Sum {4     public native static int mSum();5 }
Sum.Java

选中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 __cplusplusextern "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

下面要实现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 #endif10 /*11  * Class:     testdll_Sum12  * Method:    mSum13  * Signature: ()I14  */15 JNIEXPORT jint JNICALL _Java_testdll_Sum_mSum16   (JNIEnv *, jclass);17 18 #ifdef __cplusplus19 }20 #endif21 #endif
testdll_Sum.h

实现的方法如下:

#include "testdll_Sum.h"//前两个参数(env和obj)可以忽略JNIEXPORT jint JNICALL _Java_testdll_Sum_mSum  (JNIEnv * env, jclass obj)  {      printf("Hello world!\n");     return 5;  }
Sum.c

在Java的include文件夹下得到三个文件,一共5个文件供编译使用。

 

 

得到test.dll,放在Java工程的运行目录下即可。

选中Main.Java文件,run,得到

 

 

在我写完后,得知Java通过JNA可以很方便的调用C文件,有机会学习下。

以上内容,仅供参考。

 

Java通过JNI调用C