一來這樣速度快二來這樣子也有個更新的彈性,只是這樣一來可能就無法實現跨平台的優點。
在Java有提供JNI來實驗呼叫c\c++的dll功能
放幾個我參考的網站
- http://blog.ring.idv.tw/comment.ser?i=127
- http://www.blogjava.net/orangewhy/archive/2007/05/24/119645.html
- http://enijmax.2y.idv.tw/linux/CLib_Jni.html
- http://topatis.blog.ithome.com.tw/post/613/17245
- http://mqjing.blogspot.com/2009/04/c-gcc-library.html
一般來說會先寫個.java檔去產生Header。假設今天我一隻程式叫Hello.java
那我可以寫一個批次檔(.bat)去幫我產生要用的header
makeHeader.bat
javac Hello.java
javah -jni Hello
@pause
其中javah這個指令就是用來產生JNI Header,之後產生一個標頭檔叫Hello.h
寫一個.c或是.cpp去實作他產生DLL之後就可以給Java呼叫
不過老實說這樣很不方便,萬一Hello.java要增加新函式就會變得很不方便
因此我會比較建議用JNA+CDT的方式去做,如果要用Windows+Eclipse去開發C++的話,有兩個套件要先裝起來,一個是MinGW,另一個則是CDT
首先去下載MinGW
http://prdownloads.sourceforge.net/mingw/MinGW-5.0.3.exe
在安裝過程中選擇[Download and Install]去安裝,裝在預設目錄就行了
之後選項選擇[Candidate],要下載的東西則有
- g++ compiler
- g77 compiler
- Objective C Compiler
- MinGW Make
之後去設定環境變數
- Path變數增加[MinGW安裝目錄\bin;] ex:C:\MinGW\bin;
- 新增一個環境變數C_INCLUDE_PATH,值為:C:\MinGW\include
- 新增CPLUS_INCLUDE_PATH,值為:C:\MinGW\include\c++ \xxx;C:\MinGW\include\c++\xxx\mingw32;C:\MinGW\include\c++\xxx\backward;C:\MinGW\include
其中xxx的部分換成版本編號 ex:3.4.0
在來是安裝CDT的部分,先去官方網站找自己要的版本
http://www.eclipse.org/cdt/downloads.php
假設我要下載6.0x版,應該會看到一個連結
http://download.eclipse.org/tools/cdt/releases/galileo
這個就是eclipse的更新網址,更新的方法點選上方的[Help]->[Install New Software]
之後把那個網址Add進去之後就可以開始更新,更新完之後就可以[New]->[Project]產生一個c/c++的project
再來介紹一下JNA這玩意
官方網站:https://jna.dev.java.net/
參考網站:http://blog.csdn.net/shendl/archive/2008/12/23/3589676.aspx
http://enijmax.2y.idv.tw/linux/CLib_Jni.html
http://www.52language.com/Article/16857.html
JNA是一套Lib,他有個最大的好處,就是我不必在用javah去產生header實作才能呼叫DLL
我可以去輕易使用現有的DLL。
不過我會使用這玩意最大的玩意,就是我嘗試半天就是沒辦法生出實作javah產生header的DLL
後來使用JNA我就可以專心寫程式不用再去管那一大堆指令了
首先從官方網站把jna.jar下載下來後,在專案上按滑鼠右鍵點選[properties]->[Java Build Path]->[Libraries],選擇[Add External JARs],把剛才下載下來的jna.jar加進去後就可以使用了
那麼首先試試參考網站上的一個例子
考慮下方程式碼
import com.sun.jna.Native;
import com.sun.jna.Platform;
public class Test {
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 %d", 123);
}
}
//output:Hello 123
在這裡他呼叫的printf是msvcrt裡的printf,也就是c語言的printf函式。連native關鍵字都被我拿掉了,真是神奇。
再來試試自己寫的dll,畢竟這才是最重要的部分阿
首先我產生一個C的Project 裡面兩個檔案Hello.h跟Hello.c
Hello.h內容
__declspec(dllimport) void hello ();
Hello.c內容
#include "Hello2.h"
void hello(void)
{ printf("\nHello My Baby!! \n");}
之後用cmd去下指令編譯出兩個檔案,不過我都是寫成.bat檔
create.bat
gcc -c Hello.c
gcc -shared -o Hello.dll Hello.o -Wl,——out-implib,libmessage.a
之後就會產生DLL檔,把他放到java專案底下,這裡要注意一下,在eclipse的話是放到src目錄之前一個目錄
否則就是放到.class同個目錄下
接下來測試程式
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
public class Test {
public interface MyPrint extends Library {
MyPrint INSTANCE = (MyPrint)
Native.loadLibrary("Hello",MyPrint.class);
public void hello();
}
public static void main(String[] args) {
MyPrint.INSTANCE.hello();
}
}
//output:Hello My Baby!!
這樣就大功告成了,不過在此要注意一點的就是 Native.loadLibrary裡面不要放副檔名
他自己會去判斷是DLL或是SO檔
沒有留言:
張貼留言