java调用dll

java调用dll,第1张

调用printf()即可。

第一步是写出对固有方法及它的自变量进行声明的Java代码:

class ShowMsgBox {

public static void main(String [] args) {

ShowMsgBox app = new ShowMsgBox()

app.ShowMessage( "Generated with JNI ")

}

private native void ShowMessage(String msg)

static {

System.loadLibrary( "MsgImpl ")

}

}

在固有方法声明的后面,跟随有一个static代码块,它会调用System.loadLibrary()(可在任何时候调用它,但这样做更恰当)System.loadLibrary()将一个DLL载入内存,并建立同它的链接。DLL必须位于您的系统路径,或者在包含了Java类文件的目录中。根据具体的平台,JVM会自动添加适当的文件扩展名。

1. C头文件生成器:javah

现在编译您的Java源文件,并对编译出来的.class文件运行javah。javah是在1.0版里提供的,但由于我们要使用Java 1.1 JNI,所以必须指定-jni参数:

javah -jni ShowMsgBox

javah会读入类文件,并为每个固有方法声明在C或C++头文件里生成一个函数原型。下面是输出结果——ShowMsgBox.h源文件(为符合本书的要求,稍微进行了一下修改):

/* DO NOT EDIT THIS FILE

- it is machine generated */

#include <jni.h>

/* Header for class ShowMsgBox */

#ifndef _Included_ShowMsgBox

#define _Included_ShowMsgBox

#ifdef __cplusplus

extern "C " {

#endif

/*

* Class: ShowMsgBox

* Method: ShowMessage

* Signature: (Ljava/lang/String)V

*/

JNIEXPORT void JNICALL

Java_ShowMsgBox_ShowMessage

(JNIEnv *, jobject, jstring)

#ifdef __cplusplus

}

#endif

#endif

从“#ifdef_cplusplus”这个预处理引导命令可以看出,该文件既可由C编译器编译,亦可由C++编译器编译。第一个#include命令包括jni.h——一个头文件,作用之一是定义在文件其余部分用到的类型;JNIEXPORT和JNICALL是一些宏,它们进行了适当的扩充,以便与那些不同平台专用的引导命令配合;JNIEnv,jobject以及jstring则是JNI数据类型定义。

2. 名称管理和函数签名

JNI统一了固有方法的命名规则;这一点是非常重要的,因为它属于虚拟机将Java调用与固有方法链接起来的机制的一部分。从根本上说,所有固有方法都要以一个“Java”起头,后面跟随Java方法的名字;下划线字符则作为分隔符使用。若Java固有方法“过载”(即命名重复),那么也把函数签名追加到名字后面。在原型前面的注释里,大家可看到固有的签名。欲了解命名规则和固有方法签名更详细的情况,请参考相应的JNI文档。

3. 实现自己的DLL

此时,我们要做的全部事情就是写一个C或C++源文件,在其中包含由javah生成的头文件;并实现固有方法;然后编译它,生成一个动态链接库。这一部分的工作是与平台有关的,所以我假定读者已经知道如何创建一个DLL。通过调用一个Win32 API,下面的代码实现了固有方法。随后,它会编译和链接到一个名为MsgImpl.dll的文件里:

#include <windows.h>

#include "ShowMsgBox.h "

BOOL APIENTRY DllMain(HANDLE hModule,

DWORD dwReason, void** lpReserved) {

return TRUE

}

JNIEXPORT void JNICALL

Java_ShowMsgBox_ShowMessage(JNIEnv * jEnv,

jobject this, jstring jMsg) {

const char * msg

msg = (*jEnv)->GetStringUTFChars(jEnv, jMsg,0)

MessageBox(HWND_DESKTOP, msg,

"Thinking in Java: JNI ",

MB_OK | MB_ICONEXCLAMATION)

(*jEnv)->ReleaseStringUTFChars(jEnv, jMsg,msg)

}

若对Win32没有兴趣,只需跳过MessageBox()调用;最有趣的部分是它周围的代码。传递到固有方法内部的自变量是返回Java的大门。第一个自变量是类型JNIEnv的,其中包含了回调JVM需要的所有挂钩(下一节再详细讲述)。由于方法的类型不同,第二个自变量也有自己不同的含义。对于象上例那样的非static方法(也叫作实例方法),第二个自变量等价于C++的“this”指针,并类似于Java的“this”:都引用了调用固有方法的那个对象。对于static方法,它是对特定Class对象的一个引用,方法就是在那个Class对象里实现的。

剩余的自变量代表传递到固有方法调用里的Java对象。主类型也是以这种形式传递的,但它们进行的“按值”传递

1、总体说明:实现一个函数,传入整形数i,返回值i*i,这个函数做在DLL中,java将通过JNI调用这个函数,传入一个参数,得到返回值。

确定DLL的名称为calldll.dll,函数shanfei(int i)。2、编写java程序javacall.java,如下:public class javacall

{

static

{

System.loadLibrary("calldll")

}

public native static int shanfei(int i)

public static void main(String[] args)

{

javacall jc = new javacall()

int j

j = jc.shanfei(4)

System.out.println(j)

}

}3、编译javac javacall.java4、生成头文件javah -jni javacall

生成javacall.h文件5、制作VC++动态库建立新DLL工程,程序中添加:#include "javacall.h"

JNIEXPORT jint JNICALL Java_javacall_shanfei (JNIEnv *, jclass, jint p)

{

int j = p*p

return j

}别忘了将javacall.h复制到VC工程目录中,然后编译,如果编译说找不到jni.h文件,可以将jni.h复制到工程目录中,还可将javacall.h文件中的#include <jni.h>改为#include "jni.h",再编译。

编译生成DLL文件如“test.dll”,名称与System.loadLibrary("test")中的名称一致

vc的编译办法:cl -I%java_home%include -I%java_home%includewin32 -LD com_hode_hodeframework_modelupdate_CheckFile.c -Fetest.dll

最后在运行时加参数-Djava.library.path=[dll寄存的路径]

相关的主题文章: 6、java调用将生成的calldll.dll文件复制到javacall.java所在的目录中,运行java javacall,应该可以看到运行结果。


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/11896279.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-19
下一篇2023-05-19

发表评论

登录后才能评论

评论列表(0条)

    保存