我知道的有兩種方法,一種是直接用JNI,另一種是則是用Jacob(實質(zhì)上也用的是JNI)
成都創(chuàng)新互聯(lián)是一家以網(wǎng)站設(shè)計,開發(fā)核心業(yè)務(wù)的專業(yè)網(wǎng)站制作公司,創(chuàng)新互聯(lián)為客戶提供:軟文發(fā)稿、創(chuàng)新網(wǎng)站解決方案。我們的目標(biāo)是提高客戶網(wǎng)站項目的專業(yè)度,以創(chuàng)新和互聯(lián)的思維增加用戶體驗并有效提高潛在客戶。
先講講第一種方法
1.編寫Java程序TestDll,注意,這個類有兩個作用,一個是用來做頭文件,另外一個作用就是通過它來調(diào)用dll
public class TestDll {
static
{
System.loadLibrary("DLLSample");//載入dll
}
public native static int DoubleValue(int i);//函數(shù)聲明
}
2.編譯: javac TestDll
3.生成頭文件: javah TestDll
生成TestDll.h文件,這里面只對函數(shù)DoubleValue作了聲明
/* 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: DoubleValue
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_TestDll_DoubleValue
(JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
4.用VC制作DLL
修改DLLSample工程,程序中添加函數(shù)DoubleValue的實現(xiàn),函數(shù)名必須用jni規(guī)定格式,可以照到.h文件里的聲
明來寫:
#include "jni_md.h"
#include "TestDll.h"
JNIEXPORT jint JNICALL Java_TestDll_DoubleValue (JNIEnv *, jclass, jint p)
{
int j = p*2;
return j;
}
JNIEXPORT,JNICALL,JNIEnv *, jclass請都不要動,jint對應(yīng)是java里的int
別忘了把TestDll.h,jni.h(這個文件在JDK/include下),jni_md.h(這個文件在jdk/include/win32下)復(fù)制到VC
工程目錄中,然后編譯生成dll
5.把生成的DLLSample.dll復(fù)制到j(luò)dk/bin下(確保PATH指向了這個目錄)
6.應(yīng)用
我看到他們舉的例子都是把調(diào)用寫在了main里, 在這里我把應(yīng)用取出來放在一個Servlet類中的測試的,同樣可
以得到正確結(jié)果,這里體現(xiàn)國TestDll的第二個作用,它是調(diào)用dll的一個紐帶
......
TestDll td = new TestDll();
System.out.println("result= " td.DoubleValue(25));
.....
注意:
如果更改了TestDll的內(nèi)容或重使命名了這個文件,必須重新用它生成頭文件,在dll里也要做相應(yīng)修改,
因為必須要和java里面的聲明一致才行
----------------------------------------
本文隨寫,若有什么錯誤,請多多指出,謝謝
說明:本文是west263的博文,作者并沒有留名
我們要明白一點,C語言的function和Java語言的function是同一個單詞,在英文世界里沒有人會區(qū)別哪個是“方法”哪個是“函數(shù)”。所以翻譯成“函數(shù)”和“方法”的主要原因是因為最初引入這些編程到大陸的翻譯人員的習(xí)慣。
在Python語言中,在類中的函數(shù)常叫做“方法”。以此推測,Java萬物皆是類,基本每一個函數(shù)都在類中,所以Java中的所有的函數(shù)都叫做“方法”。
C++里面的函數(shù)叫做“函數(shù)”。
C語言、Java語言官方文檔
Python中文手冊
要在java中調(diào)用c語言的庫,需要使用Java提供了JNI。
舉例說明
在c語言中定義一個 void sayHello()函數(shù)(打印Hello World);然后在Java中調(diào)用這個函數(shù)顯示Hello Word.
現(xiàn)在分別從Java和C語言兩部分說明:
1. Java 部分
首先定義一個HelloNative,在其中申明sayHello函數(shù),函數(shù)要申明為Native 類型的.如下:
public class HelloNative {
public native void sayHello();
}
編譯這個類,生成class文件:
javac HelloWorld.java
利用javah生成需要的h文件
javah HelloNative
生成的 h文件大概如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include jni.h
/* Header for class HelloNative */
#ifndef _Included_HelloNative
#define _Included_HelloNative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloNative
* Method: sayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloNative_sayHello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
可以看一下上面自動生成的程序,程序include了jni.h,這個頭文件在 $JAVA_HOME下的include文件夾下. 還可以發(fā)現(xiàn)生成的函數(shù)名是在之前的函數(shù)名前面加上了Java_HelloNative。
2. C語言部分
根據(jù)上面生成的h文件編寫相應(yīng)的代碼實現(xiàn),建立一個 HelloNative.cpp用來實現(xiàn)顯示Hello World的函數(shù).如下:
#include stdio.h
#include "HelloNative.h"
JNIEXPORT void JNICALL Java_HelloNative_sayHello(JNIEnv *, jobject)
{
printf("Hello World!\n");
}
代碼編寫完成之后,我們再用gcc編譯成庫文件,命令如下;
gcc -fPIC -I/usr/lib/jvm/java-7-openjdk-i386/include -I/usr/lib/jvm/java-7-openjdk-i386/include/linux -shared -o libHelloNative.so HelloNative.cpp
這樣就會在當(dāng)前目錄下生成一個libHelloNative.so的庫文件.這時需要的庫已經(jīng)生成,在C語言下的工作已經(jīng)完成了.
接下來需要在Java中編寫一個程序測試一下.在程序前,需要將我們的庫載入進去.載入的方法是調(diào)用Java的 System.loadLibrary("HelloNative");
public class TestNative
{
static {
try {
System.loadLibrary("HelloNative");
}
catch(UnsatisfiedLinkError e) {
System.out.println( "Cannot load hello library:\n " + e.toString() );
}
}
public static void main(String[] args) {
HelloNative test = new HelloNative();
test.sayHello();
}
}
但是再編譯后,運行的時候,問題又出現(xiàn)了.
Cannot load hello library:
java.lang.UnsatisfiedLinkError: no HelloNative in java.library.path
Exception in thread "main" java.lang.UnsatisfiedLinkError: HelloNative.sayHello()V
at HelloNative.sayHello(Native Method)
at TestNative.main(TestNative.java:13)
載入庫失敗,但是庫明明就是放在當(dāng)前文件夾下的,怎么會載入失敗呢?
用System.getProperty("java.library.path")查看,發(fā)現(xiàn)java.library.path中并不u存在當(dāng)前的目錄.主要有以下的幾個解決辦法:
1) 將生成的庫復(fù)制到j(luò)ava.library.path有的路徑中去,當(dāng)然這樣不是很好
2) 設(shè)置環(huán)境變量export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ,將當(dāng)前的目錄加入到LD_LIBRARY_PATH中
3) 設(shè)置java 的選項,將當(dāng)前的目錄加入到其中 .java -Djava.library.path=. $LD_LIBRARY_PATH
這樣之后程序就能夠成功的運行了.可以看見顯示的"Hello World!"了
C語言是經(jīng)典的面向過程的編程語言,編程入門一般都學(xué)C語言以了解編程以及鍛煉邏輯思維能力,在一些跟硬件比較緊密的編程中也經(jīng)常用到。\x0d\x0a\x0d\x0aC++是在C語言的基礎(chǔ)上加入了面向?qū)ο蟮母拍?,成為混合型面向?qū)ο笳Z言,功能強大,但難度也大。\x0d\x0a\x0d\x0aJava是在C++的基礎(chǔ)上進行改進的,摒棄了一些C++的不足之處,語法跟C++很像,它是運行在Java虛擬機上,所以可以跨平臺,一處編譯,到處執(zhí)行。\x0d\x0a\x0d\x0a編程都是易學(xué)難精,哪個都好學(xué),哪個又都不好學(xué)。都有很好的發(fā)展前景,就看是什么方向了。底層的C、桌面應(yīng)用程序、游戲等等C++、嵌入式,網(wǎng)頁,Java。