欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

JNA相關知識

系統 1678 0

使用JNA簡單調用DLL里的函數
1、在VC下創建一個動態鏈接庫項目testJNA

2、在頭文件里聲明函數

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

  


紅色字體部分是必須的,包括定義結構體時也需要。應該是說此函數是發布的。


3、在源碼里實現函數

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

  



4、生成dll文件


5、定義一個表示鏈接庫的接口
接口TestJnaLib繼承自com.sun.jna.Library,此接口有一個實例?

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

此實例由jna通過反射自動生成。

6、定義對應dll里的方法

    int add(int first, int second);
  




7、調用本地方法

    TestJnaLib.INSTANCE.add(3, 5);
  









Jna回調Java方法:

1、在C語言部分定義帶回調函數的函數

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


紅色加粗部分是函數指針。

2、Java部分定義一個回調接口
必須繼承自com.sun.jna.Callback接口

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


Invoke方法里的參數順序與C函數的對應

3、定義回調接口的實現

    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、在表示鏈接庫實現的接口里定義要回調的本地函數

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

本地函數的函數指針用Callback 接口替代。

5、調用帶函數指針的本地函數

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

?

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

Java代碼 復制代碼 ? 收藏代碼
    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代碼 復制代碼 ? 收藏代碼
    /* 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下建立一個動態鏈接庫項目testJNA

倒數第二個。

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


5、編寫C的本地實現

C代碼 復制代碼 ? 收藏代碼
    #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、構建testJNA項目,生成testJNA.dll文件


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

8、運行Java類,調用本地方法
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相關知識:
使用JNA調用原生函數的模式:
JNA不實用native關鍵字。
JNI使用native關鍵字,使用一個個java方法來代表外部的原生函數。
JNA使用一個java接口來代表一個動態鏈接庫發布的所有函數。
對于不需要的原生函數,可以不在java接口中聲明java方法原型。

使用JNI,需要使用System.loadLibrary方法,把專門為JNI編寫的動態鏈接庫載入進來,這個動態鏈接庫實際上是真正需要的動態鏈接庫的代理。
使用JNA類庫的Native類的loadLibrary方法,是直接把需要的動態鏈接庫載入進來。使用JNA不需要編寫作為代理的動態鏈接庫,不需要編寫一行原生代碼。


跨平臺、跨語言調用原則:
盡量使用基本、簡單的數據類型;
盡量少跨平臺、跨語言傳遞數據!

Java調用原生函數時,會把數據固定在內存中,這樣原生函數才可以訪問這些Java數據。這些數據,JVM的GC不能管理,會造成內存碎片。




C語言的結構體是一個嚴格的規范,定義了內存的次序。因此,JNA中模擬的結構體的變量順序絕對不能錯。

Java調用動態鏈接庫中的C函數,實際上就是把一段內存作為函數的參數傳遞給C函數。動態鏈接庫以為這個參數就是C語言傳過來的參數。

Structure類的write()方法會把結構體的所有字段固定住,是原生函數可以訪問。


JNI技術是雙向的,既可以從Java代碼中調用原生函數,也可以從原生函數中直接創建Java虛擬機,并調用Java代碼。

原生函數可以通過函數指針實現函數回調,調用外部函數來執行任務。這就是策略模式。



Callback:
任務回調定義必須繼承自com.sun.jna.Callback接口,子類必須定義單個公有方法或一個名為callback的公有方法。必須持有到回調對象的一個存活引用。一個回調應該不拋出異常。

com.sun.jna.Library:
代表本地鏈接庫的定義。可用如下形式定義:

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


雖然結構體和結構體字段的名字可以是任意的,但他們應該盡可能接近本地定義。參數名也一樣。
此接口支持在Java端多線程、并發調用本地方法。如果本地類庫不是線程安全的,可用

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

來阻止多線程同時訪問本地代碼。


鏈接庫的搜索路徑:
jna.library.path 用戶定義的路徑;
Jna.platform.library.path 平臺定義的路徑,


com.sun.jna.Structure:
代表本地結構體的對等Java類。
當作為參數或返回值使用時,這個類被傳遞給struct * (指針);當作為另一個結構體的字段時,它被傳遞給struct (值傳遞)。
標記接口Structure.ByReference和Structure.ByValue被用來提醒默認的行為。

Structure屬性傳遞給本地字段必須是public的。可以由下面可選的修飾符:
volatile JNA不會修改字段,除非被要求,通過writeField(String);
final?? JNA會通過read()覆寫字段,字段在java這邊是不可變的。

Structure屬性的順序與類型必須與本地結構體的字段一一對應。

?

?

?

JNA相關知識


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

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

【本文對您有幫助就好】

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

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 鲁久久| 亚洲欧美色欧另类欧 | 国产成人精品.一二区 | 亚洲欧美国产日本 | 久久国产免费 | 国产亚洲欧美日韩v在线 | 99热官网 | www.国产高清 | 涩涩色综合亚洲悠悠色 | 精品国产三级 | 亚洲高清在线播放 | a视频在线免费观看 | 日日拍夜夜嗷嗷叫视频 | 国产美女啪 | 欧美日韩性生活 | 国产精品中文字幕在线 | 欧日一级片 | 久久黄视频 | 日本黄a | 东方亚洲东方欧美色二区 | 亚洲精品国产第1页 | 91精品国产日韩91久久久久久 | 国产婷婷精品av在线 | 奇米色偷偷 | 久久久久久久久99精品 | 久青草久青草高清在线播放 | 一级片九九 | 欧美在线一区二区三区 | 免费视频片在线观看 | 啪视频免费| 欧美日韩精品一区二区在线线 | 高清中文字幕免费观在线 | 欧美大胆一级视频 | 日本欧美一区二区三区视频 | 美乃雀中文字幕在线一区 | 欧美日在线 | 超碰8| 日韩在线视屏 | 免费国产午夜在线观看 | www.久久久 | 国产精品成在线观看 |