1、Java调用c++是通过jni来实现的
2、通常Java作为整个程序的框架,然后具体的函数使用c++来实现,将c++写的代码编译成动态库,然后Java在代码中调用这些动态库!
3、下面是一个例子:
c++部分,头文件
// BeCall.h : BeCall DLL 的主头文件
//
#ifndef _BE_CALL_H_
#define _BE_CALL_H_
// 包含相应的头文件
#ifdef WIN32
#include "jni.h"
#else
#include </usr/lib/jvm/jdk/include/linux/jni_md.h>
#include </usr/lib/jvm/jdk/include/jni.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
// 定义一个函数
JNIEXPORT jint JNICALL Java_TestCall_get(JNIEnv *, jclass);
// 定义一个函数
JNIEXPORT void JNICALL Java_TestCall_set(JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
c++部分,源文件
// BeCall.cpp : 定义 DLL 的初始化例程。
#ifdef WIN32
#include "stdafx.h"
#else
#endif
#include "BeCall.h"
int i = 0;
// 函数的实现
JNIEXPORT jint JNICALL Java_TestCall_get (JNIEnv *, jclass)
{
return i;
}
// 函数的实现
JNIEXPORT void JNICALL Java_TestCall_set (JNIEnv *, jclass, jint j)
{
i = j;
}
Java部分
public class TestCall
{
static
{
//System.out.print(System.getProperty("java.library.path"));
System.setProperty("java.library.path",".");
System.loadLibrary("BeCall");
}
public native static int get();
public native static void set(int i);
/**
* @param args
*/
public static void main(String[] args)
{
// TODO Auto-generated method stub
TestCall testCall = new TestCall();
testCall.set(10);
System.out.print(testCall.get());
}
}
在c++中定义的函数,例如:
Java_TestCall_set
必须要按照下面的方式命名:Java+Java类名+函数名,在上面例子中,Java类名是TestCall,Java的函数名是set,因此,函数名是
Java_TestCall_set
5、编译Java代码:javac TestCall.java 会生成一个TestCall.class的文件
6、windows下编译和调用动态库
直接使用vs进行编译即可,很方便,编译出来的结果是BeCall.dll
把BeCall.dll放到TestCall.class文件所在的目录下
直接使用 java TestCall 命令即可运行
7、Linux下编译和调用动态库
使用命令 g++ -fPIC -shared -o libBeCall.so BeCall.cpp 即可生成 动态库 libBeCall.so
此时如果直接运行 java TestCall 会出错,如下:
java.lang.UnsatisfiedLinkError: no BeCall in java.library.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1886)
这是因为找不到动态库所在的目录导致的,可以把动态库复制到/lib目录下:sudo cp libBeCall.so /lib/libBeCall.so
此时运行 TestCall就可以了