給大家介紹一個(gè)最新的訪問本機(jī)代碼的
Java
框架
—JNA
。
JNA(Java Native Access)
框架是一個(gè)開源的
Java
框架,是
SUN
公司主導(dǎo)開發(fā)的,建立在經(jīng)典的
JNI
的基礎(chǔ)之上的一個(gè)框架。
JNA
項(xiàng)目地址:
https://jna.dev.java.net/
非常強(qiáng)大、易用,功能上類似與
.NET
的
P/Invoke
。
不堪回首的
JNI
我們知道,使用
JNI
調(diào)用
.dll/.so
共享類庫是非常非常麻煩和痛苦的。
如果有一個(gè)現(xiàn)有的
.dll/.so
文件,如果使用
JNI
技術(shù)調(diào)用,我們首先需要另外使用
C
語言寫一個(gè)
.dll/.so
共享庫,使用
SUN
規(guī)定的數(shù)據(jù)結(jié)構(gòu)替代
C
語言的數(shù)據(jù)結(jié)構(gòu),調(diào)用已有的
dll/so
中公布的函數(shù)。
然后再在
Java
中載入這個(gè)適配器
dll/so
,再編寫
Java
native
函數(shù)作為
dll
中函數(shù)的代理。
經(jīng)過
2
個(gè)繁瑣的步驟才能在
Java
中調(diào)用本地代碼。
因此,很少有
Java
程序員愿意編寫調(diào)用
dll/.so
庫中的原生函數(shù)的
java
程序。這也使
Java
語言在客戶端上乏善可陳?梢哉f
JNI
是
Java
的一大弱點(diǎn)!
.NET
平臺(tái)上強(qiáng)大的
P/Invoke
而在
.NET
平臺(tái)上,強(qiáng)大的
P/Invoke
技術(shù)使我們
Java
程序員非常羨慕。使用
P/Invoke
技術(shù),只需要使用編寫一個(gè)
.NET
函數(shù),再加上一個(gè)聲明的標(biāo)注,就可以直接調(diào)用
dll
中的函數(shù)。
不需要你再使用
C
語言編寫
dll
來適配。
不遜于
P/Invoke
的
JNA
現(xiàn)在,不需要再羨慕
.NET
的
P/Invoke
機(jī)制了。
JNA
把對(duì)
dll/.so
共享庫的調(diào)用減少到了和
P/Invoke
相同的程度。
使用
JNA
,不需要再編寫適配用的
.dll/.so
,只需要在
Java
中編寫一個(gè)接口和一些代碼,作為
.dll/.so
的代理,就可以在
Java
程序中調(diào)用
dll/so
。
JNA
快速啟動(dòng)
現(xiàn)在讓我們直接進(jìn)入
JNA
的世界。
你只需要下載一個(gè)
jar
包,就可以使用
JNA
的強(qiáng)大功能方便地調(diào)用動(dòng)態(tài)鏈接庫中的
C
函數(shù)。
1
,下載
jna.jar
。
在這里
https://jna.dev.java.net/servlets/ProjectDocumentList?folderID=7408&expandFolder=7408&folderID=0
2
,現(xiàn)在你已經(jīng)可以使用
JNA
了。
為了方便你參考
JNA
的
java
類庫,我制作了《
JNA3.09API
參考手冊(cè)》,是
CHM
格式的。你可以到這里下載
http://download.csdn.net/source/900438
JNA
例子
例子
1
現(xiàn)在讓我們運(yùn)行一個(gè)
JNA
程序,感受它的強(qiáng)大威力。
1
,在
Java
項(xiàng)目中引入
jna.jar
包。
2
,創(chuàng)建一個(gè)類:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
/** Simple example of native library declaration and usage. */
public class HelloWorld {
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary)
Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),
CLibrary.class);
void printf(String format, Object... args);
}
public static void main(String[] args) {
CLibrary.INSTANCE.printf("Hello, World\n");
for (int i=0;i < args.length;i++) {
CLibrary.INSTANCE.printf("Argument %d: %s\n", i, args[i]);
}
}
}
3
,執(zhí)行,可以看到控制臺(tái)中打印出了
Hello, World
但是,請(qǐng)注意,這個(gè)程序?qū)嶋H上是使用
msvcrt.dll
這個(gè)
C
運(yùn)行時(shí)庫中的
printf
函數(shù)打印出上面這些字符的。
看,多簡單,不需要寫一行
C
代碼,就可以直接在
Java
中調(diào)用外部動(dòng)態(tài)鏈接庫中的函數(shù)!
例子
2
上面那個(gè)例子使用了操作系統(tǒng)自帶的動(dòng)態(tài)鏈接庫,現(xiàn)在我們?cè)僮约簩懸粋(gè)動(dòng)態(tài)鏈接庫試試。
1
,在
VS
中選擇
C++
語言,然后選擇創(chuàng)建一個(gè)
Win32
程序。
選擇
dll
類型。
2
,發(fā)布的
C
函數(shù)是:
#define
MYLIBAPI
extern
"C"
__declspec
(
dllexport
)
MYLIBAPI
void
say(
wchar_t
* pValue);
這個(gè)函數(shù)的實(shí)現(xiàn)是:
void
say(
wchar_t
* pValue){
std::wcout.imbue(std::locale(
"chs"
));
std::wcout<<L
"上帝說:"
<<pValue<<std::endl;
}
它需要傳入一個(gè)
Unicode
編碼的字符數(shù)組。然后在控制臺(tái)上打印出一段中文字符。
3
,生成
dll
。然后把生成的
dll
文件復(fù)制到
Eclipse
項(xiàng)目中,放在項(xiàng)目下面。
4
,在
Eclipse
中編寫以下代碼:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.WString;
/**
* @author
沈東良
Edward Shen shendl_s@hotmail.com
* 2008-11-23
下午
05:07:14
*TestDll1.dll
*/
public class TestDll1Service {
public interface TestDll1 extends Library {
/**
*
當(dāng)前路徑是在項(xiàng)目下,而不是
bin
輸出目錄下。
*/
TestDll1 INSTANCE = (TestDll1)Native.loadLibrary("TestDll1", TestDll1.class);
public void say(WString value);
}
/**
*
*/
public TestDll1Service() {
// TODO Auto-generated constructor stub
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
TestDll1.INSTANCE.say(new WString("Hello World!"));
System.out.println("HHEEH
我我們無法萬惡
");
}
}
5
,執(zhí)行這個(gè)
Java
類?梢钥吹娇刂婆_(tái)下如下輸出:
上帝說:
Hello World!
HHEEH
我我們無法萬惡
6
,上面一行是
C
語言使用
C++
的
std::wcout
輸出的。
下面一行是
Java
語言輸出的。
JNA
技術(shù)解密
JNA
工作原理
JNA
是建立在
JNI
技術(shù)基礎(chǔ)之上的一個(gè)
Java
類庫,它使您可以方便地使用
java
直接訪問動(dòng)態(tài)鏈接庫中的函數(shù)。
原來使用
JNI
,你必須手工用
C
寫一個(gè)動(dòng)態(tài)鏈接庫,在
C
語言中映射
Java
的數(shù)據(jù)類型。
JNA
中,它提供了一個(gè)動(dòng)態(tài)的
C
語言編寫的轉(zhuǎn)發(fā)器,可以自動(dòng)實(shí)現(xiàn)
Java
和
C
的數(shù)據(jù)類型映射。你不再需要編寫
C
動(dòng)態(tài)鏈接庫。
當(dāng)然,這也意味著,使用
JNA
技術(shù)比使用
JNI
技術(shù)調(diào)用動(dòng)態(tài)鏈接庫會(huì)有些微的性能損失?赡芩俣葧(huì)降低幾倍。但影響不大。
JNA
技術(shù)難點(diǎn)
1
,當(dāng)前路徑是在項(xiàng)目下,而不是
bin
輸出目錄下。
2
,數(shù)據(jù)結(jié)構(gòu)的對(duì)應(yīng)關(guān)系:
Java—C
和操作系統(tǒng)數(shù)據(jù)類型的對(duì)應(yīng)表
Java Type
|
C Type
|
Native Representation
|
boolean
|
int
|
32-bit integer (customizable)
|
byte
|
char
|
8-bit integer
|
char
|
wchar_t
|
platform-dependent
|
short
|
short
|
16-bit integer
|
int
|
int
|
32-bit integer
|
long
|
long long, __int64
|
64-bit integer
|
float
|
float
|
32-bit floating point
|
double
|
double
|
64-bit floating point
|
Buffer
Pointer
|
pointer
|
platform-dependent (32- or 64-bit pointer to memory)
|
<T>[] (array of primitive type)
|
pointer
array
|
32- or 64-bit pointer to memory (argument/return)
contiguous memory (struct member)
|
除了上面的類型,
JNA
還支持常見的數(shù)據(jù)類型的映射。
|
String
|
char*
|
NUL-terminated array (native encoding or
jna.encoding
)
|
WString
|
wchar_t*
|
NUL-terminated array (unicode)
|
String[]
|
char**
|
NULL-terminated array of C strings
|
WString[]
|
wchar_t**
|
NULL-terminated array of wide C strings
|
Structure
|
struct*
struct
|
pointer to struct (argument or return) (
or explicitly
)
struct by value (member of struct) (
or explicitly
)
|
Union
|
union
|
same as
Structure
|
Structure[]
|
struct[]
|
array of structs, contiguous in memory
|
Callback
|
<T> (*fp)()
|
function pointer (Java or native)
|
NativeMapped
|
varies
|
depends on definition
|
NativeLong
|
long
|
platform-dependent (32- or 64-bit integer)
|
PointerType
|
pointer
|
same as
Pointer
|
轉(zhuǎn)載:
http://blog.csdn.net/shendl/archive/2008/12/23/3589676.aspx
JNA—JNI終結(jié)者.rar (89.1 KB)