java通过JNI调用c++代码

java通过JNI调用c++代码

1 用java约定接口,生成头文件

创建JniHelloWorld.java

public class JniHelloWorld {
	public JniHelloWorld(){
	}
	public native void sayHello(String name);

}

生成头文件供c++使用

javah-jni JniHelloWorld

产生JniHelloWorld.h文件,里面是用c++代码规定了接口形式。

2生成动态链接库文件(http://blog.csdn.net/zjq2008wd/article/details/17582535)

用eclipsec++这个IDE生成,new->project->c++project选择SharedLibrary->Empty
Project。

这里命名为JniCpp。

创建一个cpp文件来实现头文件的接口,命名为hello.cpp。

#include <iostream>
#include "JniHelloWorld.h"

using namespace std;
JNIEXPORT void JNICALL Java_JniHelloWorld_sayHello
  (JNIEnv* env, jobject obj, jstring name)
{
	const char* pname = env->GetStringUTFChars(name, NULL);
	cout << "Hello, " << pname << endl;
}

编译出错:../JniHelloWorld.h:2:17:fatal
error: jni.h: No such file or directory

从/usr/local/lib/jdk1.7.0_55/include找到该文件,拷贝到工程里面。

将JniHelloWorld.h的#include<jni.h>改为#include"jni.h"

编译出错:../jni.h:45:20:fatal
error: jni_md.h: No such file or directory

同理,将/usr/local/lib/jdk1.7.0_55/include/linux包含到工程里面。

链接出错:/usr/bin/ld:./hello.o:
relocation R_X86_64_32 against `.rodata‘ can not be usedwhen making a shared object; recompile with -fPIC

解决方法:project->properties->setting
->tool setting->complier如下图所示添加-fPIC

把g++改为g++-fPIC。

(这里我试过直接修改makefile,发现失败,因为elicpse每次都会按照她的规则生成新的makefile)

成功了:

makeall

Buildingfile: ../hello.cpp

Invoking:GCC C++ Compiler

g++-fPIC -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"hello.d"-MT"hello.d" -o "hello.o" "../hello.cpp"

Finishedbuilding: ../hello.cpp

Buildingtarget: libJniCpp.so

Invoking:GCC C++ Linker

g++-shared -o "libJniCpp.so" ./hello.o

Finishedbuilding target: libJniCpp.so

这个libJniCpp.so就是我们所需要的动态链接库。

3java调用动态链接库

首先,让java识别到这个so的位置。(http://www.blogjava.net/miaoyachun/archive/2012/12/06/392529.html)

我是直接在JniHelloWorld类里面添加如下代码:

static{

System.out.println("load");

try{

System.setProperty("java.library.path",

System.getProperty("java.library.path")+

":/home/linger/jni");

System.out.println(System.getProperty("java.library.path"));

Field fieldSysPath =ClassLoader.class.getDeclaredField("sys_paths");

fieldSysPath.setAccessible(true);

fieldSysPath.set(null,null);

System.loadLibrary("JniCpp");

}catch(Exception e) {

// do nothing for exception

}

}

注意命名,JniCpp和libJniCpp.so,如果命名错了也是会找不到动态链接库的。

然后在这个类里面添加main函数来测试,

public static voidmain(String[]
args)

{

System.out.println("main");

JniHelloWorldshp =newJniHelloWorld();

shp.sayHello("World");

}

最后,JniHelloWorld.java文件是这样子的:

import java.lang.reflect.Field;

public class JniHelloWorld {

	static{
        System.out.println("load");
		try {
			   System.setProperty("java.library.path",
					   System.getProperty("java.library.path")+
	                    ":/home/linger/jni");
			   System.out.println(System.getProperty("java.library.path"));
	           Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
	           fieldSysPath.setAccessible(true);
	           fieldSysPath.set(null, null);
	         System.loadLibrary("JniCpp");
			  } catch (Exception e) {
		            // do nothing for exception
		        }

    }

	public JniHelloWorld(){
	}
	public native void sayHello(String name);
	public static void main(String[] args)
	{
	    System.out.println("main");
		JniHelloWorld shp = new JniHelloWorld();
		shp.sayHello("World");
	}
}

参考资料:

http://blog.csdn.net/skywalker256/article/details/4677644

较详细的介绍JNI

http://blog.csdn.net/zjq2008wd/article/details/17582535

Linux下Eclipse进行C++编程动态库so的生成与使用

http://www.blogjava.net/miaoyachun/archive/2012/12/06/392529.html

关于java.library.path

时间: 2024-10-29 21:49:36

java通过JNI调用c++代码的相关文章

Java通过JNI调用dll详细过程(转)

源:Java通过JNI调用dll详细过程 最近项目有这样一个需求,在已有的CS软件中添加一个链接,将当前登录用户的用户名加密后放在url地址中,在BS的login方法里通过解密判断,如果为合法用户则无需再次登录直接进入平台,CS软件方提供了一个加密解密的dll文件,我们需要在action中通过该dll解密,那么就涉及到java调用dll的问题. 首先我选择了JNI方式(因为网上说的另两种方式Jawin, Jacob更不会),大体流程如下: 1.写一个java的class,在类里声明所调用的库名称

JAVA的JNI调用

由于JNI调用C和调用C++差不多,而且C++中可以混合写C代码,所以这里主要是写关于JNI调用C++的部分. 一般步骤: 先是写普通的Java类,其中包括本地方法调用.  然后编译这个Java类,调用javah命令,生成.h头文件 接着,就是实现头文件中的函数:实现过程中有点比较麻烦,要知道JNI中JAVA和C/C++的类型转换,比如数组类型的转换,基本类型的转换等,最好是看文档,或者网上找相关资料. 源代码链接:http://files.cnblogs.com/GDUT/jni-demo.r

Java采用JNI调用VC++生成的dll(Java与C++交互)

应项目需求,需要android调用java,java再调用C++实现android一个图片匹配的功能,我们作为java组需要和C++和Android进行交互.下面是java和C++采用JNI的方式进行接口传参交互,我做的一个demo并运行成功. 什么是JNI? JNI全拼是Java Native Interface,中文意思为Java本地调用.JNI标准是Java平台的一部分,它允许java和其他语言的代码进行交互.JNI开始是为了本地已经编译好的语言,尤其是C和C++而设计的,我们也可以使用J

java 通过jni调用c++实现详解

Java通过JNI调用C++程序 JNI是Java Native Interface的缩写,中文为JAVA本地调用.使用JNI可以很方便的用我们的Java程序调用C/C++程序.很多时候,某些功能用Java无法实现,比如说涉及到底层驱动的一些功能,这时候我们就可以利用JNI来调用C或者C++程序来实现,这就是JNI的强大之处.但是JNI也有它的缺点,使用java与本地已编译的代码交互,通常会丧失平台可移植性. 下面是一个JNI例子,调用C++输出"hello world": 第一步:创

在Java中直接调用js代码(转载)

http://blog.csdn.net/xzyxuanyuan/article/details/8062887 JDK1.6版添加了新的ScriptEngine类,允许用户直接执行js代码. 在Java中直接调用js代码 不能调用浏览器中定义的js函数,会抛出异常提示ReferenceError: “alert” is not defined.   package com.sinaapp.manjushri;  import javax.script.ScriptEngine;  import

JAVA使用JNI调用C++动态链接库

JAVA使用JNI调用C++动态链接库 使用JNI连接DLL动态链接库,并调用其中的函数 首先 C++中写好相关函数,文件名为test.cpp,使用g++编译为DLL文件,指令如下: g++ -shared -Wl,--kill-at,--output-def,test.def -o test.dll test.cpp #如果cpp中要调用其他dll,需要在命令后面添加相关lib描述 这样就在当路径下同时生成了test.def 和 test.dll 文件 顺便说一下,.lib文件可以通过.def

1.JAVA中使用JNI调用C++代码学习笔记

Java 之JNI编程1.什么是JNI? JNI:(Java Natibe Inetrface)缩写. 2.为什么要学习JNI?  Java 是跨平台的语言,但是在有些时候仍然是有需要调用本地代码 (这些代码通常是由C/C++编写的). Sun公司提供的JNI是Java平台的一个功能强大的接口.这个JNI接口提供了Java与操作系统本地代码互相调用的功能.(即java调用C++代码) 最简单的Java调用C/C++代码步骤 1.创建TestNativeCode工程,新建cn.itcast包,新建

Java通过JNI调用C

Java调用C有多种方式,本文介绍笔者最近的学习过程,避免今后再犯类似的错误. 首先,Java肯定是调用C的动态链接库,即通过编译器编译后的dll/so文件. 下面介绍gcc编译dll的方法. 一般情况把主函数,子函数定义,子函数声明(全局变量,宏等)分别放在不同的文件中. 我们主要对子函数编译生成可用的dll,供主函数调用. 有一个工程,里面有三个文件,分别是 #include <stdio.h> #include "test.h" int main(int argc,

关于Java通过JNI调用C 动态链接库(DLL)

JNI介绍 用JNI实现Java和C语言的数据传递 JNI原理分析和详细步骤截图说明 jni的JNIEnv指针和jobject指针 JNI实现回调| JNI调用JAVA函数|参数和返回值的格式 Jni接口-深入研究参数的传递(一)