跨平台的JAVA调不跨平台的C--(JNI在Win32&&Linux下的使用)

   由于java程序需要调用C或C++的代码,不得不使用JNI。C的代码在Win32和Linux下都有相同功能的不同实现,就像JDK分几种平台版本(win32,linux,solaris等)。
   首先,看一看首先,看一看win32下调用dll文件。
    1, 新建HelloWorld.java
 1public class HelloWorld
 2
{
 3  static

 4  {
 5    try

 6    {
 7      //此处即为本地方法所在链接库名

 8      System.loadLibrary("HelloWorld");
 9    }
catch(UnsatisfiedLinkError e){
10      System.err.println( "不能加载dll文件:\n " +
e.toString() );
11    }

12  }
//end static
13 public native void SayHello(String strName);
14

15}

16
  2,  编译java文件生成HelloWorld.class文件
  3,在命令行下,javah -jni HelloWorld 生成 HelloWorld.h 文件
  
 1/* DO NOT EDIT THIS FILE - it is machine generated */
 2#include <jni.h>
 3/* Header for class HelloWorld */
 4
 5
#ifndef _Included_HelloWorld
 6
#define _Included_HelloWorld
 7
#ifdef __cplusplus
 8
extern "C" {
 9
#endif
10
/*
11 * Class:     HelloWorld
12
 * Method:    SayHello
13
 * Signature: (Ljava/lang/String;)
14 */

15JNIEXPORT void JNICALL Java_HelloWorld_SayHello
16  (JNIEnv *
, jobject, jstring);
17

18
#ifdef __cplusplus
19
}
20
#endif
21
#endif
22
  4,   编写HelloWorld.cpp
 1#include <windows.h>
 2#include "HelloWorld.h"
 3#include <stdio.h>
 4//与Hello.h中函数声明相同
 5JNIEXPORT void JNICALL Java_HelloWorld_SayHello (JNIEnv * env, jobject arg, jstring instring)
 6
{
 7//从instring字符串取得指向字符串UTF编码的指针

 8  const jbyte *str = 
 9   (const jbyte *)env->
GetStringUTFChars( instring, JNI_FALSE );
10printf("HelloWorld,%s\n"
,str);
11  //通知虚拟机本地代码不再需要通过str访问Java字符串。

12env->ReleaseStringUTFChars( instring, (const char *)str );
13return
;
14}
 
15int
 WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
16
{
17    return
 TRUE ;
18}
5,  在vc6下新建dll工程HelloWorld,加载HelloWorld.h和HelloWorld.cpp,编译生成HelloWorld.dll文件,最关键的是引用JAVAHOME\include\和JAVAHOME\include\win32的.h文件。
6,设置classpath为dll文件所在路径,新建一个测试类TestHelloWorldDLL.java
1public class HelloWorld {
2public static void main(String args[]){
3        HelloWorld hw = new HelloWorld();
4        hw.SayHello("Christmas");    
5    }

6}

7,  输出结果: HelloWorld Christmas
=======================================================================================================

 接下来,在linux下调用so试一试。
 因为linux下不能用vc所以gcc,如下命令:
#gcc -I/usr/java/include -shared -o libHelloWorld.so HelloWorld.cpp 
    运行测试程序,发现不能导入.so文件,提示no HelloWorld  in java.library.path,所以需要设置java.library.path。
 
java -Djava.library.path=`pwd` -cp .  MyNative
注意我把.so文件拷到了当前路径,其他路径设置即可!
再执行,ok了,输出正确结果!
 
最后,总结一下:
  jni的使用很简单,麻烦的是抽象出所调用dll或so文件的接口封装成native方法。另外就是生成so或dll文件以后的路径很不好控制。最重要的一点Java 的C调用通常不能移植到其他平台上,失去了“write once,run anywhere ”的美誉!但没违反重用性的规则。再者,需求来了,不这样实现能行吗?

posted on 2005-12-21 18:54 beyondduke 阅读(1827) 评论(0)  编辑  收藏 所属分类: 编程随笔


只有注册用户登录后才能发表评论。


网站导航:
 
<2005年12月>
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

导航

统计

公告


MSN联系

常用链接

留言簿(2)

随笔分类

随笔档案

我的连接

搜索

最新评论

阅读排行榜

评论排行榜