`
zorufa876
  • 浏览: 80963 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

JAVA通过JNI调用C--app开发实践(1)

 
阅读更多

从今天开始,为了好玩,希望做一个有趣android平台上的APP,但是以前没有类似的开发经验,一切从头开始,所以在过程中遇到的一些问题,能够在这里进行记录:

 

 

问题一: 由于用到jni,但是无法通过javah命令生成h头文件,比如我的HelloWord.class的目录结构是

E:\gayShe\,我在这个目录下执行E:\gayShe\jni>javah  -jni jni.HelloWorld 这个命令,报如下错误:

 

错误:无法访问 jni.HelloWorld
未找到 jni.HelloWorld 的类文件
javadoc: 错误 - 找不到类 jni.HelloWorld。
Error: 未在命令行中指定任何类。请尝试使用 -help。

 

网上搜索了一下,发现是路径不对的原因,由于我的 HelloWorld是的包路径是jni.HelloWorld,因此如果我想要生成这个h头文件,就需要手动生成一个jni目录,把class文件的目 录结构改成E:\gayShe\jni,然后在E:\gayShe\目录下执行javah -classpath . -jni jni.HelloWorld 这个命令(这里注意,-classpath和-jni之间有一个点号),那么jni_HelloWorld.h这个头文件就生成在E:\gayShe\目录下了。

 

问题二: 需要通过C编译器生成DLL(Windows系统)或者SO(Linux系统)文件,我这次是生成了DLL文件,下载一个VC6++,然后选择新建工程,注意,这里需要选择“Win32 Dynamic-link Libray”

这个工程,然后写好代码,完成编译,生成dll文件(在这个工程的debug目录下),然后再把这个dll文件拷贝到java工程目录下,比如我的工程路径是D:\work\testExamples,那么我这边只需要把dll文件放到D:\work\testExamples这个目录下就行了。注意,前面的路径只是在我用单元测试的时候是有效的,而当我在用jboss去加载这个dll的时候,目前我只发现有两个方法可以确保找到dll,一个是把dll放到C:\Windows\System32路径下,另一个就是设置path变量,不知道有没有第三种方法。

 

以下是程序加载dll文件的顺序:1应用程序的安装目录 2当前工作目录 3系统目录(就是system32文件夹 )4路径变量。

 

jni的相关概念:JNI是java的一部分,通过此,可以实现跨平台,与其他语言进行交互,具体可参考网上的这篇文档:

 

原网址:http://www.cnblogs.com/mandroid/archive/2011/06/15/2081093.html

 

JAVA基础之理解JNI原理

JNI是JAVA标准平台中的一个重要功能,它弥补了JAVA的与平台无关这一重大优点的不足,在JAVA实现跨平台的同时,也能与其它语言(如C、C++)的动态库进行交互,给其它语言发挥优势的机会。
有了JAVA标准平台的支持,使JNI模式更加易于实现和使用。在此总结了下面这个知识图:
实例:
环境说明:ubuntu 10.4.2 LTS系统
程序清单1:src/com/magc/jni/HelloWorld.java

写道
/**
*
*/
package com.magc.jni;

/**
* @author magc
*
*/
public class HelloWorld {

static {

System.loadLibrary("Hello");

}

public native void DisplayHello();
/**
* @param args
*/
public static void main(String[] args) {

new HelloWorld().DisplayHello();
 

 进入src目录下,编译该JAVA类,
命令:javac ./com/magc/jni/HelloWorld.java
在该HelloWorld.java所在目录下生成HelloWorld.class
然后使用javah生成头文件,
命令:javah -jni com.magc.jni.HelloWorld
在当前目录下生成com_magc_jni_HelloWorld.h头文件,此文件供C、C++程序来引用并实现其中的函数
程序清单2:com_magc_jni_HelloWorld.h
写道
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_magc_jni_HelloWorld */

#ifndef _Included_com_magc_jni_HelloWorld
#define _Included_com_magc_jni_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_magc_jni_HelloWorld
* Method: DisplayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_magc_jni_HelloWorld_DisplayHello
(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
 

注:1)、此头文件是不需要用户编译的,直接供其它C、C++程序引用。
     2)、此头文件中的Java_com_magc_jni_HelloWorld_DisplayHello(JNIEnv * , jobject)方法,是将来与动态链接库交互的接口,并需要名字保持一致。
 程序清单3:src/jni_helloworldImpl.cpp

写道
#include <jni.h>
#include "com_magc_jni_HelloWorld.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_com_magc_jni_HelloWorld_DisplayHello
(JNIEnv *env, jobject obj)
{
printf("From jni_helloworldImpl.cpp :");
printf("Hello world ! \n");
return;
}
 

此C++文件实现了上述头文件中的函数,注意方法函数名要保持一致。
编译生成动态库libHello.so,
命令:g++ -shared -I /usr/lib/jvm/java-6-openjdk/include jni_helloworldImpl.cpp -o libHello.so
成功后,便会在当前目录下生成动态链接库libHello.so文件。
有了具体实现的动态库后,就可以运行JAVA调用JNI程序类的native方法了,
命令:java -Djava.library.path=. com.magc.jni.HelloWorld
输入结果即为:From jni_helloworldImpl.cpp :Hello world ! 
 本文参考部分内容参考:
2、《Android应用开发详解》

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics