日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

JNA相關(guān)知識(shí)

系統(tǒng) 1731 0

使用JNA簡(jiǎn)單調(diào)用DLL里的函數(shù)
1、在VC下創(chuàng)建一個(gè)動(dòng)態(tài)鏈接庫(kù)項(xiàng)目testJNA

2、在頭文件里聲明函數(shù)

    extern "C" _declspec(dllexport) int add(int first, int second);

  


紅色字體部分是必須的,包括定義結(jié)構(gòu)體時(shí)也需要。應(yīng)該是說此函數(shù)是發(fā)布的。


3、在源碼里實(shí)現(xiàn)函數(shù)

    int add(int first, int second) {
	printf("(c) test jna : %d + %d = %d", first, second, first + second);
	return first + second;
}

  



4、生成dll文件


5、定義一個(gè)表示鏈接庫(kù)的接口
接口TestJnaLib繼承自com.sun.jna.Library,此接口有一個(gè)實(shí)例?

    TestJnaLib INSTANCE = (TestJnaLib)Native.loadLibrary("testJNA.dll", TestJnaLib.class);
  

此實(shí)例由jna通過反射自動(dòng)生成。

6、定義對(duì)應(yīng)dll里的方法

    int add(int first, int second);
  




7、調(diào)用本地方法

    TestJnaLib.INSTANCE.add(3, 5);
  









Jna回調(diào)Java方法:

1、在C語言部分定義帶回調(diào)函數(shù)的函數(shù)

    extern "C" _declspec(dllexport) void methodWithCallback(int (*fp)(int left, int right), int left, int right);
  


紅色加粗部分是函數(shù)指針。

2、Java部分定義一個(gè)回調(diào)接口
必須繼承自com.sun.jna.Callback接口

    public interface FunCallBack extends Callback {
	int invoke(int left, int right);
}
  


Invoke方法里的參數(shù)順序與C函數(shù)的對(duì)應(yīng)

3、定義回調(diào)接口的實(shí)現(xiàn)

    public class CallbackFunImpl implements FunCallBack {
	@Override
	public int invoke(int left, int right) {
		System.out.printf("in java :%d + %d = %d\n", left, right, left + right);
		return left + right;
	}
}
  



4、在表示鏈接庫(kù)實(shí)現(xiàn)的接口里定義要回調(diào)的本地函數(shù)

    void methodWithCallback(Callback callback, int left, int right);
  

本地函數(shù)的函數(shù)指針用Callback 接口替代。

5、調(diào)用帶函數(shù)指針的本地函數(shù)

    TestJnaLib.INSTANCE.methodWithCallback(new CallbackFunImpl(), 4, 6)
  

?

1、編寫需要使用Jni的Java類文件

Java代碼 復(fù)制代碼 ? 收藏代碼
    public class JniCall {
	static {
		System.loadLibrary("testJNA");
	}
	
	public native static int add(int first, int second);
	
	public static void main(String[] args) {
		int first = 3;
		int second = 4;
		
		System.out.printf("print in java : %d + %d = %d", first, second, add(first, second));
	}
}

  


本地方法必須聲明為native。

2、編譯出class文件,用javah從class文件生成C的頭文件JniCall.h

C代碼 復(fù)制代碼 ? 收藏代碼
    /* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JniCall */

#ifndef _Included_JniCall
#define _Included_JniCall
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     JniCall
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_JniCall_add
  (JNIEnv *, jclass, jint, jint);


typedef struct Student {
	char * name;
	int age;
	int height;

}StudentObj;

#ifdef __cplusplus
}
#endif
#endif

  




3、在VC下建立一個(gè)動(dòng)態(tài)鏈接庫(kù)項(xiàng)目testJNA

倒數(shù)第二個(gè)。

4、把生成的JniCall.h和$JAVA_HOME/include/jni.h、$JAVA_HOME/include/win32jni_md.h拷貝到vc項(xiàng)目testJNA的目錄下


5、編寫C的本地實(shí)現(xiàn)

C代碼 復(fù)制代碼 ? 收藏代碼
    #include "stdafx.h"


BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    return TRUE;
}

JNIEXPORT jint JNICALL Java_JniCall_add(JNIEnv *, jclass, jint first, jint second) {
	printf("print in c    : %d + %d = %d \n", first, second, first + second);
	return first + second;
}

  



6、構(gòu)建testJNA項(xiàng)目,生成testJNA.dll文件


7、把testJNA.dll拷貝到$JAVA_HOME/jre/bin目錄下

8、運(yùn)行Java類,調(diào)用本地方法
D:\Java\jdk1.6.0_02\bin>java JniCall
print in c??? : 3 + 4 = 7
print in java : 3 + 4 = 7
D:\Java\jdk1.6.0_02\bin>



JNA相關(guān)知識(shí):
使用JNA調(diào)用原生函數(shù)的模式:
JNA不實(shí)用native關(guān)鍵字。
JNI使用native關(guān)鍵字,使用一個(gè)個(gè)java方法來代表外部的原生函數(shù)。
JNA使用一個(gè)java接口來代表一個(gè)動(dòng)態(tài)鏈接庫(kù)發(fā)布的所有函數(shù)。
對(duì)于不需要的原生函數(shù),可以不在java接口中聲明java方法原型。

使用JNI,需要使用System.loadLibrary方法,把專門為JNI編寫的動(dòng)態(tài)鏈接庫(kù)載入進(jìn)來,這個(gè)動(dòng)態(tài)鏈接庫(kù)實(shí)際上是真正需要的動(dòng)態(tài)鏈接庫(kù)的代理。
使用JNA類庫(kù)的Native類的loadLibrary方法,是直接把需要的動(dòng)態(tài)鏈接庫(kù)載入進(jìn)來。使用JNA不需要編寫作為代理的動(dòng)態(tài)鏈接庫(kù),不需要編寫一行原生代碼。


跨平臺(tái)、跨語言調(diào)用原則:
盡量使用基本、簡(jiǎn)單的數(shù)據(jù)類型;
盡量少跨平臺(tái)、跨語言傳遞數(shù)據(jù)!

Java調(diào)用原生函數(shù)時(shí),會(huì)把數(shù)據(jù)固定在內(nèi)存中,這樣原生函數(shù)才可以訪問這些Java數(shù)據(jù)。這些數(shù)據(jù),JVM的GC不能管理,會(huì)造成內(nèi)存碎片。




C語言的結(jié)構(gòu)體是一個(gè)嚴(yán)格的規(guī)范,定義了內(nèi)存的次序。因此,JNA中模擬的結(jié)構(gòu)體的變量順序絕對(duì)不能錯(cuò)。

Java調(diào)用動(dòng)態(tài)鏈接庫(kù)中的C函數(shù),實(shí)際上就是把一段內(nèi)存作為函數(shù)的參數(shù)傳遞給C函數(shù)。動(dòng)態(tài)鏈接庫(kù)以為這個(gè)參數(shù)就是C語言傳過來的參數(shù)。

Structure類的write()方法會(huì)把結(jié)構(gòu)體的所有字段固定住,是原生函數(shù)可以訪問。


JNI技術(shù)是雙向的,既可以從Java代碼中調(diào)用原生函數(shù),也可以從原生函數(shù)中直接創(chuàng)建Java虛擬機(jī),并調(diào)用Java代碼。

原生函數(shù)可以通過函數(shù)指針實(shí)現(xiàn)函數(shù)回調(diào),調(diào)用外部函數(shù)來執(zhí)行任務(wù)。這就是策略模式。



Callback:
任務(wù)回調(diào)定義必須繼承自com.sun.jna.Callback接口,子類必須定義單個(gè)公有方法或一個(gè)名為callback的公有方法。必須持有到回調(diào)對(duì)象的一個(gè)存活引用。一個(gè)回調(diào)應(yīng)該不拋出異常。

com.sun.jna.Library:
代表本地鏈接庫(kù)的定義??捎萌缦滦问蕉x:

    MyNativeLibrary INSTANCE = (MyNativeLibrary)Native.loadLibrary("mylib", MyNativeLibrary.class);
  


雖然結(jié)構(gòu)體和結(jié)構(gòu)體字段的名字可以是任意的,但他們應(yīng)該盡可能接近本地定義。參數(shù)名也一樣。
此接口支持在Java端多線程、并發(fā)調(diào)用本地方法。如果本地類庫(kù)不是線程安全的,可用

    Native.synchronizedLibrary(com.sun.jna.Library)
  

來阻止多線程同時(shí)訪問本地代碼。


鏈接庫(kù)的搜索路徑:
jna.library.path 用戶定義的路徑;
Jna.platform.library.path 平臺(tái)定義的路徑,


com.sun.jna.Structure:
代表本地結(jié)構(gòu)體的對(duì)等Java類。
當(dāng)作為參數(shù)或返回值使用時(shí),這個(gè)類被傳遞給struct * (指針);當(dāng)作為另一個(gè)結(jié)構(gòu)體的字段時(shí),它被傳遞給struct (值傳遞)。
標(biāo)記接口Structure.ByReference和Structure.ByValue被用來提醒默認(rèn)的行為。

Structure屬性傳遞給本地字段必須是public的??梢杂上旅婵蛇x的修飾符:
volatile JNA不會(huì)修改字段,除非被要求,通過writeField(String);
final?? JNA會(huì)通過read()覆寫字段,字段在java這邊是不可變的。

Structure屬性的順序與類型必須與本地結(jié)構(gòu)體的字段一一對(duì)應(yīng)。

?

?

?

JNA相關(guān)知識(shí)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!??!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 龙岩市| 仁化县| 临邑县| 临海市| 嵊泗县| 丰台区| 连平县| 南雄市| 泌阳县| 泸溪县| 五原县| 四川省| 登封市| 海伦市| 托克逊县| 山丹县| 从江县| 芜湖市| 峨山| 江西省| 澳门| 万宁市| 仙居县| 云南省| 会东县| 环江| 抚宁县| 嘉禾县| 理塘县| 嘉黎县| 连南| 公主岭市| 从化市| 高邮市| 南雄市| 玉屏| 株洲市| 娱乐| 长顺县| 黄骅市| 德格县|