jni调用三方dll实例(绝对简单可用)

时间:2024.4.13

jni调用三方dll实例(绝对简单可用)

一.废话在前(可不看):

自学难啊,我是个懒人,一般情况下,是非常不喜欢写东西的,更不想转载别人的资料然后骗分、骗人气。只有自己经过非常惨痛的教训然后最后百度以后,还是没有办法解决的情况下,然后最终无意中搞定了,这种情况下,我写写,尽量减少大家走到弯路,一开始我打算百度,然后照葫芦画瓢,资料我收集了一堆,调了N++久,可惜这个瓢还是没画好,最终,我还去书店买书,可惜也没有找到相关资料, 还是最终自己想通了这个过程,才搞定,废话完毕,资料如下:

二.准备工作:

先配置环境,

1. 配置java环境,最起码要保证在cmd里面可以运行java、javac、javah命令。

2. 准备一个vc++的环境吧,我用的是vc2010。

3. 先将java安装目录下的C:\Program Files\Java\jdk1.5.0_11\include下面的jni.h文件和

C:\Program Files\Java\jdk1.5.0_11\include\win32的jni_md.h文件拷贝到vc环境下的include文件下面

环境就这样了,完成了。

备注(可不看):

加点便于理解的心得,实际上,jni是用java调用自己写的dll在通过这个dll调用第三方的dll,才开始了,我将自己写的这个dll看的很神奇了,完全照网上的资料写,写的我哭,最终我搞定了,我才发现,原来,自己写的这个dll仍然是c++的dll,说起来和java是没有关系的,之所以像java,其原因是最终有个include <jni>, 实际上我最终解决的办法,就是请了一位兄弟,帮我写了一个c++调用的代码,根据他的代码,我先完成了c++调用一个dll在通过这个dll调用三方的dll,成功以后, 我修改了中间的dll,在使用java类调用,居然成功了。对了,在多说一句,c++有个调用限制的关键字不要用啊,就默认就好,不过那个名字编译的c是需要的。废话完毕,代码操作如下:

三.代码操作如下(为便于理解,我参数传递就用int好了):

1. 先新建一个dll当作三方的dll,操作如下:

A.新建项目

打开vc++环境,新建项目—win32项目(修改路径自定义,输入项目名称fmydll) —下一步—选择dll—选择空项目(便于理解)—项目名称上面点击右键—属性 —配置属性—常规—点击字符集—修改为使用多字节字符集(为防止会报错)

B.新建.h文件

在项目的头文件夹上点击右键—添加新建项—选中头文件(.h)—名称输入fmydll 拷贝代码如下:

#ifndef fmydll_H_

#define fmydll_H_

extern "C" int _declspec(dllexport) fMax(int a);

#endif

// extern "C"让编译的名称不改变,_declspec(dllexport)这个好像是必须的

// fMax(int a)这个是我申明的方法

C.新建cpp文件

在项目的源文件夹上点击右键—添加新建项—选中c++文件(.cpp)—名称输

入fmydll拷贝代码如下:

#include "fmydll.h"

#include<iostream>

extern "C" int _declspec(dllexport) fMax(int a)

{

printf("调用函数tesdll的函数func_test1:返回值为%d\n");

return a*10;

}

D.生成dll

点击生成—重新生产解决方案—关闭这个解决方案。

三方的dll生成就算完成了,然后到这个项目的目录下面debug文件夹下把fmydll.dll拷贝出来,放在一边待用。

2. 新建java调用类,操作如下(可单独建立一个文件夹比如叫jni):

新建文本文档,更改其名称为testdll.java然后拷贝如下代码:

public class testdll

{

static

{

System.loadLibrary("mydll");

}

public native static int Max(int a);

public static void main(String[] args)

{

testdll test = new testdll();

test.Max(10);

System.out.println(test.Max(1)); //可更改参数看效果

}

}

保存关闭以后,cmd界面cd进入这个目录,输入javac testdll.java回车产生.class文件,然后javah testdll产生.h文件,现在可以把刚刚那个第三方的fmydll.dll拷贝进来只用拷贝这个文件,就可以了。现在jni文件夹里有4个文件。

3. 新建自己写的中间dll文件(就是这里啊,卡了我N++天啊):

A.新建项目

打开vc++环境,新建项目—win32项目(修改路径自定义,输入项目名称mydll) —下一步—选择dll—选择空项目—项目名称上面点击右键—属性—配置属性—

常规—点击字符集—修改为使用多字节字符集

B.新建.h文件

在项目的头文件夹上点击右键—添加新建项—选中头文件(.h)—名称输入mydll

拷贝刚刚javah生产的.h中代码到这个文件中,代码如下(我看都没看,直接复制过来):

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

#include <jni.h>

/* Header for class testdll */

#ifndef _Included_testdll

#define _Included_testdll

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class: testdll

* Method: Max

* Signature: (I)I

*/

JNIEXPORT jint JNICALL Java_testdll_Max

(JNIEnv *, jclass, jint);

#ifdef __cplusplus

}

#endif

#endif

C.新建cpp文件

在项目的源文件夹上点击右键—添加新建项—选中c++文件(.cpp)—名称输入mydll拷贝代码如下:

#include <windows.h>

#include <jni.h>

#include "mydll.h"

typedef int( *abc)(int);

JNIEXPORT jint JNICALL Java_testdll_Max(JNIEnv *, jclass, jint a)

{

abc ab;

int k=0;

HINSTANCE hDLL=LoadLibrary("fmydll.dll");

ab=(abc)GetProcAddress(hDLL,"fMax");

if(ab)

{

k=ab(a);

}

return k+1;

}

D.生成dll

点击生成—重新生产解决方案—关闭这个解决方案。

将这个mydll.dll拷贝到刚刚那个jni文件夹下,现在这个文件夹下有5个文件了, 1个.java文件,1个.class文件,1个.h文件,两个.dll文件然后运行java testdll就可以看到效果了。

备注(重要啊):我的代码完成以后,在我的环境下测试没有问题,我就放在了,csdn上,结果下载下来以后,对方告诉我无法使用,是直接使用我打包好的文件,我很奇怪,详细询问其测试环境,没发现问题,自己测试以后仍然没有问题,其和我是环境唯一之差别是其是vc6.0,无奈之下,建立了一个虚拟机,安装vc6.0,测试发现果然无法使用,已经打包好的dll居然仍然受到环境影响,这个不太懂原因,反正,请大家注意了。

补充:

1.我的两个dll文件,一个是将传过来的参数直接乘10,一个是将传过来的值+1所以,比如我传值是1那结果就是1*10+1=11,依次类推。

2.至于参数传递的难题,看看再说吧。


第二篇:java调用dll


本章用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)

更多相关推荐:
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篇)