IBM的developerWorks 中国上又一个jni的中文教程,我现在也在用jni,咱们可以互相学习!

解决方案 »

  1.   

    这几天我在IBM中文及SUN官方网站中找了不少关于JNI的文章,受益非浅,希望有相关问题的朋友,可到那找查相关资料.1)在 Windows 中实现 Java 本地方法
    http://www-900.ibm.com/developerWorks/cn/java/jnimthds/index.shtml
    2)Java Native Interface: Programmer's Guide and Specification 
    http://java.sun.com/docs/books/jni上面的文章对JNI介绍非常详细,对JNI有性趣的朋友可以看看.这有个例子,是能过一个中间DLL调用无权修改DLL库,贴出来与大家分享.
    有一myDll.dll库,接口Trim(LPSTR lpString),功能是把lpString中的空格去掉。文件原码如下:
    #include <string.h>
    #include <windows.h>#ifdef _cplusplus
    extern "C"{
    #endif
    __declspec(dllexport) void Trim(LPSTR lpString)
    {
    int iLength = strlen(lpString);
    int iCount = 0;
    char *lpChar = lpString;
    int i;
    for(i=0;i<iLength;i++)
    {
    if( *lpChar != ' ' )
    {
    lpString[ iCount ] = *lpChar;
    iCount ++;
    }
    lpChar ++;
    }
    lpString[iCount ++] = 0;
    }#ifdef _cplusplus
    }
    #endif(用VC6的cl编译该文件生成动态链接库,cl -LD myDll.c -FemyDll.dll )这里假设我们不能得到该动态链接库的原代码,只有DLL及LIB文件,在通过JNI用java调用时,由于没有DLL原代码修改权限,需要我们自己用C/C++再做一个中介库DLL2,java调用这个中介库,该中介库再调用原如的DLL库,间接实现java本地方法的调用。
    下面是我做的例子,环境:Win2000Server,JDK1.3,VC6.0先编一个java程序,java2dll.java,代码如下:
    public class Java2dll
    {//声明要用到的本地方法cTrim由中介库(java2dll.dll)实现,它又调用了myDll.dll库的Trim(...)函数
    private native String cTrim(String str);
    static
    {
    System.loadLibrary( "java2dll" );  //加载本地方法(java2dll为动态链接库文件名)
    } //自己定义的一个java方法,调用本地方法cTrim(),有点多余,实际上你可直接访问本地方法cTrim()
    public String javaTrim(String str)
    {
    return cTrim(str);
    } //演示结果
    public static void main(String[] args)
    {
    Java2dll ss = new Java2dll();
    String str1="I love You.";
    String str2=ss.javaTrim(str1);
    System.out.println("调用c DLL前:");
    System.out.println("str1="+str1);
    System.out.println("调用c DLL后:");
    System.out.println("str2="+str2);
    }
    }编译该文件,生成Java2dll.class文件: 
    javac Java2dll.java
    生成C的头文件Java2dll.h:  
    javah -jni Java2dll用C编写中介库java2dll.c
    #include <stdio.h>
    #include "java2dll.h"JNIEXPORT jstring JNICALL Java_Java2dll_cTrim
     (JNIEnv *env, jobject obj, jstring str)
    {
    const char *strTemp;
    strTemp=(*env)->GetStringUTFChars(env,str,NULL);
    //错误出现时
    if(strTemp==NULL)
    {
    return NULL;
    } //调用myDll.dll库中的Trim()方法,去掉strTemp中的空格
    Trim(strTemp);
    return (*env)->NewStringUTF(env, strTemp); (*env)->ReleaseStringUTFChars(env,str,strTemp);
    }
    说明:如果你用C++编写,cpp文件,上面代码中的“(*env)”应改为“env”编译生成java2ddl.dll文件。
    用VC6的cl编译。
    cl -Id:\jdk13\include -Id:\jdk13\include\win32 -LD java2dll.c myDll.lib -Fejava2dll.dll
    说明:-Id:\jdk13\include指明JNI需要的头文件.h位置,D:\JDK13为我的JDK安装目录
    -LD 表明要生成动态链接库 
    myDll.lib或 -link myDll.lib表明要把myDll.dll链接上,否则中介库java2dll找不到Trim(..)方法。
    您可用cl /?得到HELP帮助。编译成功后,可得到中介库java2dll,运行一下,检查结果。
    java Java2dll好了,你自己试一下吧。如有问题与我联系:[email protected]
      

  2.   

    .class,.h,.c,.dll在同目录下,
    然后在环境变量中设置path为该目录,在classpath中设置该目录和.dll文件名,
    运行.class, 总是抛出java.lang.UnsatisfiedLinkError, 好象System.loadLibrary("hello")找不到hello.dll,不知道错在什么地方?
    我的文件在包jnitst中,
    我用javah生成.h时在.class文件同目录下用javah HelloWorld和javah -jni HelloWorld总是提示Error:class HelloWorld could not be found. 
    要用javah -jni -classpath D;\...\jnitst\ HelloWorld,才能生成头文件. 
    这是为什么? 是不是生成头文件有问题才造成运行时抛出UnsatisfiedLinkError?整个过程如下:
    我写了个HelloWorld.java文件,
    public class HelloWorld {
      public HelloWorld() {
      }
        public native void displayHelloWorld();
        static {
            System.loadLibrary("hello");
        }
        public static void main(String[] args) {
            new HelloWorld().displayHelloWorld();
        }
    }
    生成.class,然后用javah指令生成了HelloWorld.h文件,
    #include <jni.h>#ifndef _Included_HelloWorld
    #define _Included_HelloWorld
    #ifdef __cplusplus
    extern "C" {
    #endif
    JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld
      (JNIEnv *, jobject);#ifdef __cplusplus
    }
    #endif
    #endif实现了HelloWorldImp.c:
    #include <jni.h>
    #include "HelloWorld.h"
    #include <stdio.h>JNIEXPORT void JNICALL 
    Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj) 
    {
        printf("Hello world!\n");
        return;
    }然后生成hello.dll:
    cl -Ic:\java\include -Ic:\java\include\win32
          -LD HelloWorldImp.c -Fehello.dll