[Java的 – Ç] 在Java中的C函数调用 – 调用Java的C函数

你有没有想写一个Java程序库,但不会像某些语言 (如C) 执行? 这是一个原因,你阅读这篇文章, 或者你想使用从C函数,你可以跑得更快的Java程序的一些其他原因做!

要做到这一点, 你需要使用JNI库 (Java本地接口), 它可以从Java,反之亦然调用C函数. 基本上, 我们将用C编写的功能, 翻译成和Java库调用函数通过JNI该库. 我们将转向通过例如,它逐渐学会调用阶乘函数. 注意:我写了下面的文件相同的文件夹的所有桌面.

在执行过程中, 他在Ubuntu上工作, Linux发行版在Windows或其他可能略有不同. 我写这篇文章后协商 2 帖子 从Java调用C函数从Java调用C函数, 然而,在实施过程中遇到了一些错误,我也贴的解决方案总是.

目录
步 1: 创建并转化为类文件的Java文件
步 2: 通过创建一个JAVAH头文件
步 3: 编译C库共享
步 4: 运行Java程序
修正了一些错误

步 1: 创建并转化为类文件的Java文件


在这个阶段,我们需要加载一个图书馆和函数声明是从C写的.

class CallCFunction {
	
	// report funcion write in C.
	private native long factorial(int n);
	public static void main(String[] args) {
		CallCFunction ccf = new CallCFunction();
		int n = 5;
		System.out.println(n + "! = " + ccf.factorial(5));
	}
	
	// load library factorial to use.
	static {
		System.loadLibrary("factorial");
	}
}

创建文件后,然后将其与命令翻译:

javac CallCFunction.java

步 2: 通过创建一个JAVAH头文件

C程序写在声明的Java文件的功能因子, 因此,我们需要创建头文件可用于.

javah -jni CallCFunction

上执行命令后, 文件 CallCFunction.h 将创建. 你注意线路 15,16, 这是我们将在C程序编写函数.

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

#ifndef _Included_CallCFunction
#define _Included_CallCFunction
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     CallCFunction
 * Method:    factorial
 * Signature: (I)J
 */
JNIEXPORT jlong JNICALL Java_CallCFunction_factorial
  (JNIEnv *, jobject, jint);

#ifdef __cplusplus
}
#endif
#endif

步 3: 编译C库共享


创建文件 factorial.c 含有阶乘函数. 复制 2 当前 15, 16 CallCFunction.h文件,并添加我们下面的变量程序.

#include <jni.h>  
#include <stdio.h>  
#include "CallCFunction.h"   
JNIEXPORT jlong JNICALL Java_CallCFunction_factorial (JNIEnv *env, jobject obj, jint n)
{
	printf("funcion 'factorial' create in C programn");
	int i;
	long result = 1;
	for (i = 2; i <= n; i++)
	{
		result *= i;
	}

	return result;
}

在这, 排 4 是阶乘函数, jlong 仅将返回值作为长, 2 参数 JNIEnv的* ENVjobject OBJ 是默认的,你不需要注意 (我也弄不明白这件事), 第一个参数 3 是 我们jint 是指变量 INTñ 分别在功能 阶乘(INTñ) 文件CallCFunction.java.

现在,我们将创建一个图书馆和它分享给包含文件夹的java (你的目录可以包含不同的java). 在文件我们装库CallCFunction.java 阶乘 命令 的System.loadLibrary(“阶乘”);, 因此,我们的图书馆拥有多个字符串 LIB 即前 libfactorial.so

gcc -shared -I/usr/lib/jvm/jdk1.8.0_05/include/ factorial.c -o libfactorial.so

步 4: 运行Java程序


现在我们单独运行程序享受成功.

java -Djava.library.path=. CallCFunction

-Djava.library.path =. 被告知该程序可以找到刚刚在当前目录下创建的库 (libfactorial.so文件夹). 也可以将环境变量设置为与命令的目录 出口LD_LIBRARY_PATH =. (在底部的点), 同时可以运行在命令权 java的CallCFunction

调用Java中Ç

修正了一些错误


在执行过程中, 我遇到的一些误区, 如果你像我一样尝试以下解决方案, 如果有其他错误,你可以在这里分享到交换.

1. 无法转换java命令带
如果你不能用命令javac的java的jdk安装维修不过,也许你还没有为它设置环境变量. 你查一下java文件, javac的, JAVAH位于任意目录,然后继续设置环境变量的文件夹. 假设中的JDK “/usr / lib目录/ JVM / jdk1.8.0_05 /”

export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_05/
export PATH=$JAVA_HOME/bin:$PATH

2. 没有找到该库jni.h
如果翻译错误,这个图书馆没有找到,那么也许它没有设置环境变量使用. 你需要这样做. 他的例子:

export LD_LIBRARY_PATH=/usr/lib/jvm/jdk1.8.0_05/include/

3. 错误创建头文件
在创建一个头文件的过程 (CallCFunction.h), 您可能会遇到下面的错误:

Exception in thread "main" java.lang.IllegalArgumentException: Not a valid class name: HelloWorld
	at com.sun.tools.javac.api.JavacTool.getTask(JavacTool.java:129)
	at com.sun.tools.javac.api.JavacTool.getTask(JavacTool.java:107)
	at com.sun.tools.javac.api.JavacTool.getTask(JavacTool.java:64)
	at com.sun.tools.javah.JavahTask.run(JavahTask.java:503)
	at com.sun.tools.javah.JavahTask.run(JavahTask.java:329)
	at com.sun.tools.javah.Main.main(Main.java:46)

当您在不包含创建时的翻译文件* *的.java .class文件的目录中执行命令的. 换句话说,无法找到的* .class. 您需要设置 类路径 以包含类文件的文件夹. 假设它位于 桌面.

javah -jni -classpath /home/nguyenvanquan7826/Desktop/ HelloWorld

4. 没有找到该库jni_md.h
你找出这个库计算机. 猫, 它位于 /usr / lib目录/ JVM / jdk1.8.0_05 /在include / linux, 现在只是把它复制到 /usr / lib目录/ JVM / jdk1.8.0_05 /有/ (forder文件包含jni.h).