您的位置:首页 > 编程语言 > Java开发

JNI之一:基础 && JAVA调用win dll实例

2010-02-11 16:19 295 查看
       JNI是Java Native Interface的缩写,译为Java本地接口。它允许Java代码和其他语言编写的代码进行交互。在android中提供JNI的方式,让Java程序可以调用C语言程序。android中很多Java类都具有native接口,这些接口由本地实现,然后注册到系统中。以下这个图可以很好的说明问题:    


        android主要的JNI代码放在以下的路径中:frameworks/base/core/jni/,这个路径中的内容被编译成库libandroid_runtime.so,这是个普通的动态库,被放置在目标系统的/system/lib目录下。此外,android还有其他的JNI库。JNI中的各个文件,实际上就是普通的C++源文件;在android中实现的JNI库,需要连接动态库libnativehelper.so。

(1)以Android源码根目录/frameworks/base/services/jni/目录下有一个onload.cpp文件。onload.cpp文件上部分为注册函数的声明,下部分为注册函数,只有通过这些注册函数,上层才有可能调用注册的JNI方法。这些注册函数是由同目录下的其他.cpp文件中实现,如register_android_server_VibratorService这个函数是在com_android_server_VibratorService.cpp文件中实现的。注册代码如下:

int register_android_server_VibratorService(JNIEnv *env)
{
return jniRegisterNativeMethods(env, "com/android/server/VibratorService",
method_table, NELEM(method_table));
}

其中jniRegisterNativeMethods为注册JNI方法函数,此函数的第二个参数对应着java类即VibratorService.java的文件名(即VibratorService.java (frameworks\base\services\java\com\android\server) ),第三个参数为注册的方法表:

static JNINativeMethod method_table[] = {
{ "vibratorExists", "()Z", (void*)vibratorExists },
{ "vibratorOn", "(J)V", (void*)vibratorOn },
{ "vibratorOff", "()V", (void*)vibratorOff }
};

这里定义的三个函数就可以直接在VibratorService.java中被调用,只不过在该文件头部要以native申明函数。这三个函数的实现是在Vibrator.c (hardware\libhardware_legacy\vibrator)中,不同的JNI函数实现方法和地方是不同的。

(2)方法列表说明,static const JNINativeMethod method_table[]方法列表的原型如下:

typedef struct {
const char* name;
const char* signature;
void* fnPtr;
} JNINativeMethod;

 Andorid使用了一种Java 和 C 函数的映射表数组,并在其中描述了函数的参数和返回值。第一个变量name是Java中函数的名字;第二个变量signature,用字符串描述了函数的参数和返回值;第三个变量fnPtr是函数指针,指向C函数。其中比较难以理解的是第二个参数,例如:()Z  (J)V  ()V。实际上这些字符是与函数的参数类型一一对应的,"()" 中的字符表示参数,后面的则代表返回值。例如()V 就表示void Func(),(II)V 表示void Func(int, int),具体的每一个字符的对应关系如下:

字符   Java类型      C类型

V      void              void

Z       jboolean     boolean

I        jint                int

J       jlong            long

D      jdouble       double

F      jfloat            float

B      jbyte            byte

C      jchar           char

S      jshort          short

数组则以"["开始,用两个字符表示

[I       jintArray      int[]

[F     jfloatArray    float[]

[B     jbyteArray    byte[]

[C    jcharArray    char[]

[S    jshortArray   short[]

[D    jdoubleArray double[]

[J     jlongArray     long[]

[Z    jbooleanArray boolean[]

如果JAVA类位于一个嵌入类,则用$作为类名间的分隔符,比如:"android/os/FileObserver$ObserverThread"

===========================================================================================================

        下面举一个实例,运行Java程序直接调用WINDOWS的对话框:

(1)新建一个TestNew.java文件,输入以下内容:

public class TestNew {
public static native void hello(String msg);
static{
System.loadLibrary("TestNew");
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
hello("hello,kitty!");
}
}

        在配置好java的环境变量C:\Program Files\Java\jdk1.6.0_13\bin之后,用javac TestNew.java命令就生成了TestNew.class文件。

(2)在命令行中用javah TestNew,在class文件的基础上生成TestNew.h(就是jni代理stub的接口),内容如下:

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

#ifndef _Included_TestNew
#define _Included_TestNew
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:     TestNew
* Method:    hello
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_TestNew_hello
(JNIEnv *, jclass, jstring);

#ifdef __cplusplus
}
#endif
#endif

(3)在VC 6.0中新建一个win32 Dynamic-Link Library项目,项目名是TestNew。DLL类型选择a simple dll project,之后打开项目所在的文件目录,把步骤(2)生成的TestNew.h拷贝到此目录。点击左边中间的FileView,切换到文件浏览模式,在Header Files上点击右键,选择Add
Files to Folder…。选择TestNew.h文件,点击OK。

      打开StdAfx.h文件,再最后面添加几行语句,#include <jni.h>,#include "TestNew.h",加完如下:

#include <windows.h>
#include <jni.h>
#include "TestNew.h"

       打开TestNew.cpp,在最后面添加一段代码:

JNIEXPORT void JNICALL Java_TestNew_hello(JNIEnv * env, jclass obj, jstring jMsg)
{
const char *strMsgPtr = env->GetStringUTFChars( jMsg , 0);
MessageBox( 0, strMsgPtr,"Message box from VC++ ", 0 );
env->ReleaseStringUTFChars( jMsg, strMsgPtr);
}

(4)在VC的菜单上选择Tools-Options…,打开选项对话框。在Directories文件夹,添加上jdk所在文件夹下的include和include\win32文件夹。



点击VC上的菜单项Build-Build All,生成TestNew.dll。

(5)将VC项目Debug文件夹中的TestNew.dll复制到TestNew.class所在的文件夹下。在命令行下输入java TestNew,弹出MessageBox对话框。调用win32
api成功。如下:



参考原文:http://www.cnblogs.com/mandroid/archive/2011/06/15/2081093.html

参考原文:http://www.iteye.com/topic/304594#814127

参考原文:http://blog.csdn.net/flydream0/article/details/7088514
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jni java android include import