`
hellbaby666
  • 浏览: 12082 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

JNI调用原始dll总结

 
阅读更多

这两天被JNI折腾疯了,而其中困扰我时间最长的问题竟然都是环境问题。。总结一下JNI调用原始dll(不是包含java生成的头文件之后再生成的dll)的过程。

JNI能调用的是符合规范的dll程序,需要根据javah得到的头文件生成。因此当需要调用一个原始dll时,需要我们自己再写一个符合jni规范的dll,来调用原始dll。也就是一个中间层。

1、java生成头文件

用eclipse写完以下代码:

package com.aaa.netcard;

public class Netcard {
	
	public native void displayHelloWorld();
	
	public native int displayPlus(int a, int b);
	
	public native int displayCalculator(int a, int b);
	
	static {
        System.loadLibrary("calculator");
    }
	
	public static void main(String[] args){
		Netcard card = new Netcard();
		System.out.println(card.displayCalculator(5, 99));
	}
}

写完以后保存,eclipse就会在bin文件夹下自动生成class文件。在bin目录下打开cmd,输入javah -jni com.aaa.netcard.Netcard。回车,生成成功。注意要写包名。

生成了com_aaa_netcard_Netcard.h。此文件第三步用到。

2、原始dll。

自己写了一个简单的加减乘的origin.dll。

// origin.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"
#include "origin.h"

extern "C"_declspec(dllexport) int plus(int a, int b) {
	return a+b;
}

extern "C"_declspec(dllexport) int minus(int a, int b) {
	return a-b;
}

extern "C"_declspec(dllexport) int times(int a, int b) {
	return a*b;
}

注意关键词extern "C" _declspec(dllexport)。_declspec(dllexport)表示要输出的函数/类,extern"C"指明用C的编译方式。(详见上一篇博文)

3、完成jni调用的dll,对原始dll进行包装。

原始dll是不能直接调用的。需要调用的话需要再写一个dll将原始dll载入。

先打开第一步生成的com_aaa_netcard_Netcard.h看一下。

#ifndef _Included_com_aaa_netcard_Netcard
#define _Included_com_aaa_netcard_Netcard
#ifdef __cplusplus
extern "C" {
#endif

/*
 * Class:     com_aaa_netcard_Netcard
 * Method:    displayCalculator
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_aaa_netcard_Netcard_displayCalculator
  (JNIEnv *, jobject, jint, jint);

#ifdef __cplusplus
}
#endif
#endif

新建一个dll项目calculator,将origin.dll放在calculator/debug目录下,放在这里不用在loadLibrary时写origin.dll的绝对路径。接下来我们就在此dll工程的calculator.cpp中实现java生成的头文件中的方法。将com_aaa_netcard_Netcard.h拷贝到工程目录下并include进来。注意函数名参数等等写法要一致。可以看到从java到c++数据类型经过了转换,int变成了jint。

JNIEXPORT jint JNICALL Java_com_aaa_netcard_Netcard_displayCalculator
  (JNIEnv *, jobject, jint, jint);


// calculator.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <jni.h>
#include "calculator.h"
#include "com_aaa_netcard_Netcard.h"
using namespace std;

typedef int(*Dllfun)(int, int);

JNIEXPORT jint JNICALL Java_com_aaa_netcard_Netcard_displayCalculator
  (JNIEnv *, jobject, jint a, jint b)
{
	Dllfun original;	
	HINSTANCE hdll;
	hdll=LoadLibrary(TEXT("origin.dll"));
	if(hdll==NULL){
		FreeLibrary(hdll);
	}
	original=(Dllfun)GetProcAddress(hdll,"plus");
	if(original==NULL){
		FreeLibrary(hdll);
	}
	try{
		return original(a,b);
	} catch (const char * str){
		cout<<"fail"<<endl;
		return 1111;
	}
}

生成了calculator.dll。将此dll粘贴到java项目根目录下。编译运行,控制台输出了调用原始dl得到l的计算结果。成功。


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics