java调用dll

时间:2024.5.9

本章用Hello World示例带你领略JNI编程。

2.1 Overview

准备过程:

1. 创建一个类(HelloWorld.java)

2. 使用javac编译该类

3. 利用javah -jni产生头文件

4. 用本地代码实现头文件中定义的方法

5. Run

译注:

在一个特定环境中,写本地实现的过程是不同的(如Android)。

javah主要是生成头文件和函数签名(每个方法和成员都有签名,后有详细介绍),通过

javah学习如何正确的写法。

注意:如上述HelloWorld.java,编译后的文件为HelloWorld.class, 用 $javah HelloWorld

来产生头文件,不要带末尾的".class"。

2.2 Declare the Native Method

HelloWorld.java

class HelloWorld {

private native void print();

public static void main(String[] args) {

new HelloWorld().print();

}

static {

System.loadLibrary("HelloWorld");

}

}

HelloWrold类首先声明了一个private native print方法. static那几行是本地库。

在Java代码中声明本地方法必须有"native"标识符,native修饰的方法,在Java代码中

只作为声明存在。

在调用本地方法前,必须首先装载含有该方法的本地库. 如HelloWorld.java中所示,置

于static块中,在Java VM初始化一个类时,首先执行这部分代码,这可保证调用本地方

法前,装载了本地库。

装载库的机制,后有介绍。

2.3 Compile the HelloWorld Class

$javac HelloWorld.java

2.4 Create the Native Method Header File

$javah -jni HelloWorld

译者:"-jni"为默认参数,可有可无.

上述命令,生成HelloWorld.h文件. 关键部分如下:

JNIEXPORT void JNICALL

Java_HelloWorld_print (JNIEnv *, jobject);

现在,请先忽略两个宏:JNIEXPORT和JNICALL。 你会发现,该函数声明,接受两个参数,

而对应的Java代码对该函数的声明没有参数。第一个参数是指向JNIEnv结构的指针; 第

二个参数,为HelloWorld对象自身,即this指针。

译注:

JNIEnv是JNI核心数据之一,地位非常崇高,所有对JNI的调用都要通过此结构。

2.5 Write the Native Method Implementation

必须根据javah生成的本地函数声明实现函数,如下:

#include <jni.h>

#include <stdio.h>

#include "HelloWorld.h"

JNIEXPORT void JNICALL

Java_HelloWorld_print(JNIEnv *env, jobject obj)

{

printf("Hello World!\n");

return;

}

请注意:"jni.h"文件必须被包含,该文件定义了JNI所有的函数声明和数据类型。

2.6 Compile the C Source and Create a Native Library

请注意,生成的本地库的名字,必须与System.loadLibrary("HelloWorld");待装载库

的名字相同。

Solaris:

$cc -G -I/java/include -I/java/include/solaris HelloWorld.c -o libHelloWorld.so

-G: 生成共享库

Win:

$cl -Ic:\java\include -Ic:\java\include\win32 -MD -LD HelloWorld.c -FeHelloWorld.dll

-MD:保证与Win32多线程C库连接(译者:Win上分静态、动态、动态多线程...C库)

-LD: 生成动态链接库

2.7 Run the Program

Solaris or Win:

$java HelloWorld

输出:

Hello World!

运行前,必须保证连接器,能找到待装载的库,不然,将抛如下异常: java.lang.UnsatisfiedLinkError: no HelloWorld in library path

at java.lang.Runtime.loadLibrary(Runtime.java)

at java.lang.System.loadLibrary(System.java)

at HelloWorld.main(HelloWorld.java)


第二篇:JNI使用小例子(windows下java调用C++动态链接库)-LXL


用JNI调用C++动态链接库

编程环境:

Windows操作系统

jdk1.5

Eclipse

VC6.0

一、使用 Java 的 JNI 调用 C/C++ 的动态联结库有个固定的步骤,下面将以一个最简单的 HelloWorld 例子程序来说明调用过程。这个 HelloWorld 的例子只是简单的显示 HelloWorld 消息。 通过这个例子可以了解调用流程。

第一步、编写java类

首先,创建一个名为jnitest的Eclipse工程,并新建一个src源代码目录。这里我们编写两个java类,一个命名为HelloWorld,一个命名为TestDLL。HelloWorld中包含一个本地方法displayHelloWorld(),TestDLL用于测试这个本地方法。HelloWorld的源码如下:

HelloWorld.java 源码

public class HelloWorld {

public native void displayHelloWorld(); ①

static {

//System.loadLibrary( "HelloWorld" ); ②

System.load(System.getProperty("user.dir") + "\\PositionCorrect.dll");③ }

}

TestDLL 源码如下:

TestDLL.java 源码

public class TestDLL {

public static void main(String[] args){

HelloWorld helloWorld = new HelloWorld();

helloWorld.displayHelloWorld();

}

}

【说明】:

(1)是java本地方法申明;

(2)" HelloWorld " 是要装入的动态链接库名称。

装入动态链接库, 使用这种方法加载的话,dll文件存放的位置和JVM搜索的路径都要注意,先将生成的 DLL 拷贝到 jnitest 工程的D:\workspace\jnitest\bin 下面,然后设置 DLL 搜索路径(环境变量 PATH )为 D:\workspace\jnitest\bin ( JNI 并没有规定必须将 dll 放在与 class 文件相同的目录,只要确保 JVM 能搜索到 DLL 即可)③。重新启动 Elipse 后,运行测试程序,将看到控制台输出“ Hello World !”

注意,③必须设置好 DLL 搜索路径,或者将 dll 拷贝到

C:\WINDOWS\system32 下面。这里,我折腾了不少时间,才搞定。

(3)System.getProperty("user.dir")获得的是当前工程目录,即

D:\JAVA\workspace\jnitest

第二步、编译Java类

在Eclipse工具中编译Java类,编译后的class文件会自动放入工程目录下的bin目录中,在我的例子中,路径是D:\JAVA\workspace\jnitest\bin。

第三步、生成C++头文件

在windows中打开一个DOS命令窗口,我电脑上DOS的默认路径是C:\Users\s001,此处可以不修改默认路径,后面生成的.h文件就会自动放在改路径下,如果这个默认路径不好找,可以输入d:命令,将路径修改为D盘下,路径了解后,就要键入javah –classpath D:\JAVA\workspace\jnitest\bin HelloWorld 命令生成头文件HelloWorld.h。内容如下:

HelloWorld.h 源码

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class HelloWorld */

#ifndef _Included_HelloWorld

#define _Included_HelloWorld

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class: HelloWorld

* Method: displayHelloWorld

* Signature: ()V

*/

JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld

(JNIEnv *, jobject);

#ifdef __cplusplus

}

#endif

#endif

注意,不要修改这个头文件。

第四步、在VC中编写本地方法实现

用VC6创建名为HelloWorldWin32动态链接库工程(Dynamic Link Library)。将上述头文件HelloWorld.h拷贝到HelloWorld工程目录下,

将C:\Program Files\Java\jdk1.5.0_06\include目录下的jni.h和

C:\Program Files\Java\jdk1.5.0_06\include\win32目录下的jni_md.h

拷贝到C:\Program Files\Microsoft Visual Studio\VC98\Include目录下。在VC IDE中新建HelloWorld.cpp文件,实现头文件中声明的方法并编译成DLL。 HelloWorld.cpp 源码

#include "HelloWorld.h"

#include <stdio.h>

/*

* Class: HelloWorld

* Method: displayHelloWorld

* Signature: ()V

*/

JNIEXPORT void JNICALL Java_HelloWorld_displayHelloWorld

(JNIEnv *, jobject)

{

printf( "Hello World!\n" );

return ;

}

第五步、在Java中运行测试程序

先将生成的DLL拷贝到jnitest工程的目录下D:\JAVA\workspace\jnitest,刷新一下java工程,Run As Java Application即可。

二、传整型返回整型

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、编译成class文件

4、生成头文件

5、制作VC++动态链接库

建立新DLL工程,程序中添加:

#include "javacall.h"

JNIEXPORT jint JNICALL Java_javacall_shanfei (JNIEnv *, jclass, jint p) // jclass应该是jobject,这里要与头文件中此类型保持一致

{

int j = p*p;

return j;

6、java调用

三、传入两个整型数,返回整型数组

1、总体说明:在java中要传入两个int数给本地方法,在VC中对本地方法进行实现,并返回int数组,在java中得到本地方法返回的int[]并打印出来.

2、编写java程序PositionCorrect.java

public class PositionCorrect {

public native int[] GpsCoorEncrypt(int i,int j);

static {

if(isWindowsOS()){

}

else{

}

}

/**

} * 判断当前操作是否Windows. * * @return true---是Windows操作系统 */ public static boolean isWindowsOS(){ boolean isWindowsOS = false; String osName = System.getProperty("os.name"); if(osName.toLowerCase().indexOf("windows")>-1){ isWindowsOS = true; } return isWindowsOS; } System.load(System.getProperty("user.dir") + "/PositionCorrect.dll"); System.load(System.getProperty("user.dir") + "\\PositionCorrect.dll");

2、编译成class文件

3、生成头文件PositionCorrect.h,源码如下:

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class PositionCorrect */

#ifndef _Included_PositionCorrect

#define _Included_PositionCorrect

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class: PositionCorrect

* Method: GpsCoorEncrypt

* Signature: (II)[I

*/

JNIEXPORT jintArray JNICALL Java_PositionCorrect_GpsCoorEncrypt (JNIEnv *, jobject, jint , jint);

#ifdef __cplusplus

}

#endif

#endif

【说明】

(1)jintArray对应Java中的int[]

(2)Java_PositionCorrect_GpsCoorEncrypt

Java指Java程序;PositionCorrect指java中包含本地方法的类;GpsCoorEncrypt指要实现的本地方法,此处在Eclipse中创建的类放在了缺省包中,如果将PositionCorrect.java放在包JNIGPS下,则头文件相应的位置就变成

Java_JNIGPS_PositionCorrect_GpsCoorEncrypt

生成头文件时路径不变,运行的文件要改成:包名.class文件

(3)(JNIEnv *, jobject, jint , jint);

这一部分需要和下一步生成的.cpp文件中的方法的参数一致

4、制作VC++动态链接库

建立新DLL工程,程序中添加PositionCorrect.cpp文件,源码如下:

#include "PositionCorrect.h"

#include <stdio.h>

JNIEXPORT jintArray JNICALL Java_PositionCorrect_GpsCoorEncrypt (JNIEnv *env, jobject obj, jint lLongitude, jint lLatitude) {

jintArray iarr;// 定义数组对象

jint length = 2;

iarr =env->NewIntArray(length);//新建一个jintArray

jint buf[]={lLongitude,lLatitude};//定义一个jint类型的buffer把原始

的数组copy到这个buf中去

//返回一个jint类型的数组

//可以先往一个数组中输入值,然后把这个数组copy到jintArray中 env->SetIntArrayRegion(iarr, 0, length, buf);//将buf中的值复制到jintArray中去,数组copy

for(int i=0; i<length; i++)

printf("ELEMENT %d IS %d\n", i, buf[i]);

printf( "The end!\n" );

return iarr;

}

编译后生成dll

5、java调用,将dll文件放在工程目录下,编写使用本地方法的java文件 主要代码如下:

double x = 121.508652;

double y = 38.877323;

int longx = (int) (x * 100000);

int longy = (int) (y * 100000);

int xy[] = new int[2];

xy = positionCorrect.GpsCoorEncrypt(longx,longy);

for(int i=0;i<xy.length;i++)

System.out.println(xy[i]);

longx = xy[0];

longy = xy[1];

x = longx/100000.0;

y = longy/100000.0;

String sx,sy,s;

sx = String.valueOf(x);

sy = String.valueOf(y);

s = "经度:" + sx +"纬度:" + sy;

System.out.println(s);

问题:

1、Exception in thread "Thread-4" java.lang.UnsatisfiedLinkError: GpsCoorEncrypt

可能是VC中cpp文件的函数名与头文件中的不对应

更多相关推荐:
java调用第三方dll心得

最近在开发j2ee的项目中需要读取面部识别考勤终端机中的数据厂商提供二次开发需要的就是一个开发指南说明书和2个dll文件HwDevCommdllHDCPUtilsdll其中重要的就是HwDevCommdll用到...

Java设计模式学习心得

Java设计模式学习心得IT168技术文档整个设计模式贯穿一个原理面对介面编程而不是面对实现面向物件编程应该改爲面向介面编程目标原则是降低耦合增强灵活性一创建模式1设计模式之Factory工厂方法和抽象工厂使用...

java学习心得

Java学习心得在学习了近一个学期java后我有了一点自己的见解Java是面向对象的具有平台无关性所以现在被广泛的应用于很多领域也是因为老师在开始上课的时候就给我们讲过这些所以带有兴趣和动力去学习java程序设...

Java学习心得

Java实验报告通过学习Java和c语言我觉得编程真的很高级但是对于我来说它又是那么的望尘莫及它是一门抽象的课程也是一门技术型的活我总觉得学习计算机这类人必须有一种创新型的思维可我却又很欠缺这一思维通过一个学期...

自学Java心得

要学好java找一份工作需要很大的毅力具体学多长时间就可以找工作要看个人的悟性和学习能力以我们宿舍6个人来说计算机专业大专学历我比较笨在大学里自学了一年左右的时间毕业后在北京一家做移动增值的公司上班了同宿舍的其...

java经典学习经验

给学Java的大学生们分享一些经验想来学习Java也有两个年头了永远不敢说多么精通但也想谈谈自己的感受写给软件学院的同仁们帮助大家在技术的道路上少一点弯路说得伟大一点是希望大家为软件学院争气其实最主要的还是大家...

自学Java心得

要学好java找一份工作需要很大的毅力具体学多长时间就可以找工作要看个人的悟性和学习能力以我们宿舍6个人来说计算机专业大专学历我比较笨在大学里自学了一年左右的时间毕业后在北京一家做移动增值的公司上班了同宿舍的其...

java自学心得

Java自学心得体会学习一门新的知识不可能指望只看一本或者两本书就能够完全掌握需要有一个循序渐进的阅读过程我推荐Oreilly出版的Java系列书籍在这里我只想补充一点看法很多人学习Java是从Thinking...

java学习心得

本文由junpeng258贡献doc文档可能在WAP端浏览体验不佳建议您优先选择TXT或下载源文件到本机查看java是一种面向对象语言真正的面向对象任何函数和变量都以类class封装起来java所有的源码以及编...

学习Java的心得体会

第一我在假期期间自己自学发现还有很多很多的知识要学第二软件或者是系统的编辑过程是一个庞大的系统工程短的时间要几个月长的时间要一年以上第三编软件的成员要统一思想就是说使用的名称不但要统一而且名称要见其名知其义这个...

java初学者学习心得

学习Java心得体会学习了一学期的Java课程觉得是该总结自己的心得体会了开始学习任何一门课包括java兴趣最重要一直觉得自己在学计算机编程语言学习了很多但每门语言都停留在知识边缘地带都没深入到它们的精华部分对...

Java学习心得体会

诚信创新开放合作JAVA的面向对象编程课堂笔记面向对象主要针对面向过程面向过程的基本单元是函数什么是对象EVERYTHINGISOBJECT万物皆对象所有的事物都有两个方面有什么属性用来描述对象能够做什么方法告...

java调用第三方dll文件心得(1篇)