JAVA調(diào)用C/C++動態(tài)庫 開發(fā)筆記

前言:

這次的項目經(jīng)歷讓我嘗了一次苦頭,在最后一切順利成功執(zhí)行的時候,就決定要寫下我人生的第一篇博客。
本次項目的動態(tài)庫與正常動態(tài)庫不同的2個情況是:一是動態(tài)庫dll內(nèi)部需要調(diào)用一個與dll在同級目錄下的一個配置文件;二是動態(tài)庫在運行過程中會向動態(tài)庫dll同級目錄下創(chuàng)建并寫入一個日志文件(我這邊說的同級目錄可能不太準(zhǔn)確顷歌,具體后文會提到)。


</br>

一幔睬、調(diào)用方式:

JAVA調(diào)用C/C++動態(tài)庫有很多方法眯漩,常用的有JNI(Java Native Interface)、JNA(Java Native Access)溪窒。

  • JNI:早在JAVA1.1版本就開始支持坤塞,它定義了一種公用的語法,當(dāng)java和c/c++雙方都遵循該語法時澈蚌,可以互相調(diào)用摹芙。所以使用JNI不能直接調(diào)用一般的C/C++庫,而必須借助于一個中間動態(tài)庫宛瞄,該中間動態(tài)庫實現(xiàn)了JAVA-JNI語法-C/C++的轉(zhuǎn)換(或者你所調(diào)用的動態(tài)庫原生就封裝了JNI)浮禾。如果對C++稍微懂一點,其實使用起來也不難份汗。
  • JNA:在C#中盈电,使用[DLLImport]可以非常方便的調(diào)用原生的C/C++動態(tài)庫,所以sun公司開發(fā)了JNA來使JAVA可以像C#一樣方便的調(diào)用動態(tài)庫杯活。不過在使用過程中感覺內(nèi)部原理還是使用了JNI的語法庫匆帚。不過至少對于我們不懂C++的來說,可以直接調(diào)用原生的動態(tài)庫旁钧,而不需要再去生成一個C++的中間動態(tài)庫了吸重。

所以這次在嘗試了JNI之后還是選擇了JNA。

</br>

二歪今、關(guān)于x32和x64:

如果C/C++動態(tài)庫使用x32嚎幸,那必須運行在x32的Tomcat上,并且使用x32的JRE寄猩。所以如果不幸拿到股東動態(tài)庫嫉晶,未提供x64版本,那只能單獨部署x32服務(wù)器提供對應(yīng)的接口田篇,而x64主站點通過http方式調(diào)用該接口程序來訪問動態(tài)庫替废。

如果在x64Tomcat上加載x32版本動態(tài)庫,將得到如下錯誤信息:

"Can't load IA 32-bit .dll on a AMD 64-bit platform"

調(diào)用方法及DLL存放位置:

先來簡單的看一下JNI和JNA兩種方式加載動態(tài)庫的代碼:

JNI:
public class ImportDllTest {
    //加載動態(tài)庫
    static{
        //通過決定地址加載動態(tài)庫
        //System.load("d:\\C2JavaTest.dll");
        //通過庫名加載動態(tài)庫斯辰,不加.dll后綴舶担,自適應(yīng).dll和liunx平臺的.so
        System.loadLibrary("C2JavaTest");
    }
    //定義動態(tài)庫接口方法
    public native String subString(String str, int startIndex, int length);

    public static void main(String[] args){
        ImportDllTest importDll = new ImportDllTest();
        String str = importDll.subString("test",1,2);
    }
}
JNA:

引用JNA包

<dependency>
    <groupId>com.sun.jna</groupId>
    <artifactId>jna</artifactId>
    <version>3.0.9</version>
</dependency>

定義接口類,繼承com.sun.jna.Library

//必須繼承com.sun.jna.Library
public interface ImportDllTest extends Library {

    //加載動態(tài)庫彬呻,使用動態(tài)庫名稱加載衣陶,不帶.dll后綴,會自動識別liunx環(huán)境下的.so庫闸氮。也可以使用決定地址加載動態(tài)庫
    public static ImportDllTest Instance = (ImportDllTest) Native.loadLibrary("C2JavaTest", ImportDllTest.class);

    //定義動態(tài)庫接口方法
    String subString(String str, int startIndex, int length);

    
    public class Main{
        public static void main(String[] args){
            String str = ImportDllTest.Instance.subString("test",1,2);
        }
    }
}
關(guān)于是否加載到動態(tài)庫:

兩種加載動態(tài)庫都可以使用動態(tài)庫名稱或者絕對路徑來加載剪况,在調(diào)試過程中,JNA如果沒找到動態(tài)庫并不會給出明確的提示蒲跨,而JNI的加載方法會明確拋出找不到動態(tài)庫的異常译断,所以即使是使用JNA方式,但在一開始不確定是否將動態(tài)庫放在了正確位置或悲,是否成功的加載了動態(tài)庫的時候可以借助于JNI的Systetm.loadLibrary來協(xié)助判斷是否成功的加載了對應(yīng)的動態(tài)庫孙咪。
</br>

三堪唐、動態(tài)庫位置:

加載動態(tài)庫都可以使用決定地址來加載。但本次項目加載的動態(tài)庫會需要調(diào)用同級目錄下的配置文件翎蹈,使用絕對地址的方式我是沒能成功的加載到配置文件(因為也不清楚動態(tài)庫里實際加載配置文件的具體實現(xiàn))淮菠。使用動態(tài)庫名稱加載,那動態(tài)庫到底應(yīng)該放在哪里荤堪,網(wǎng)上查了很多資料合陵,有放system32的,有放jdk/jre的澄阳,有放tomcat里的拥知,有放環(huán)境變量配置里的。在追求盡量不給后續(xù)運維造成太大困擾(放系統(tǒng)system32碎赢,或jdk/jre低剔,部署時很容易忘記或錯亂),盡可能找最優(yōu)的方案肮塞。
最后我借助于動態(tài)庫生成的日志文件户侥,來判斷默認(rèn)加載動態(tài)庫的路徑:

應(yīng)用程序:

Main方法測試時,動態(tài)庫及配置文件需要放到運行時選擇的工作目錄下峦嗤。


動態(tài)庫和配置文件要放在:


同時生成的日志文件也將會在該目錄下

Tomcat部署程序

Tomcat部署時蕊唐,嘗試過很多方式,但是最后選擇了Tomcat的bin目錄

cd Tomcat/bin

</br>

四烁设、JAVA與C/C++參數(shù)對應(yīng)

java的char是2字節(jié)替梨,byte是1字節(jié);c/c++的char是1字節(jié)装黑;

作為JAVA傳入C/C++參數(shù):
JAVA C/C++
byte[] char[]/char*
String char[]/char*
int int
作為JAVA中傳入副瀑,C/C++里out的參數(shù):
C/C++ JAVA
char[]/char* byte[]

調(diào)用是要先將定義的byte數(shù)組空間定義好,c++中才可以在已經(jīng)定義的空間中寫值恋谭。

//out參數(shù)長度8字節(jié)內(nèi)容
byte[] out_param = new byte[8];

</br>

五糠睡、總結(jié)

  • 可以借助于JIN確定動態(tài)庫是否能正確加載到。如果動態(tài)庫不需要配置文件疚颊,完全可以使用決定路徑來進行加載狈孔。
  • 明確動態(tài)庫的版本,是x32還是x64材义。不同版本要使用對應(yīng)的tomcat和jre均抽。
  • 確定傳遞參數(shù)類型,java中一定要記得不可以使用char來和c++的char交互其掂,一定是要byte或String(為什么String可以油挥,猜測可能JIN或JNA在內(nèi)部轉(zhuǎn)換成了byte)。
  • 最后如果動態(tài)庫能有人員配合一起調(diào)試,那是一個美好的事情深寥。
    </br>
    </br>

這次把成功的幾個關(guān)鍵點調(diào)用整理在此攘乒。本次項目也是因為調(diào)用的古董動態(tài)庫,沒有文檔惋鹅,沒有錯誤說明持灰,所有返回都靠猜測,所以不確實是java調(diào)用問題還是本身業(yè)務(wù)問題负饲。前前后后折騰好幾周,最后總算還是有了一個好的結(jié)果喂链。

以上有任何不對的地方返十,敬請指正。

</br>
</br>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末椭微,一起剝皮案震驚了整個濱河市洞坑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蝇率,老刑警劉巖迟杂,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異本慕,居然都是意外死亡排拷,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門锅尘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來监氢,“玉大人,你說我怎么就攤上這事藤违±烁” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵顿乒,是天一觀的道長议街。 經(jīng)常有香客問我,道長璧榄,這世上最難降的妖魔是什么特漩? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮骨杂,結(jié)果婚禮上拾稳,老公的妹妹穿的比我還像新娘。我一直安慰自己腊脱,他們只是感情好访得,可當(dāng)我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般悍抑。 火紅的嫁衣襯著肌膚如雪鳄炉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天搜骡,我揣著相機與錄音拂盯,去河邊找鬼。 笑死记靡,一個胖子當(dāng)著我的面吹牛谈竿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播摸吠,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼空凸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了寸痢?” 一聲冷哼從身側(cè)響起呀洲,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎啼止,沒想到半個月后道逗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡献烦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年滓窍,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片巩那。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡贰您,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拢操,到底是詐尸還是另有隱情锦亦,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布令境,位于F島的核電站杠园,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏舔庶。R本人自食惡果不足惜抛蚁,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望惕橙。 院中可真熱鬧瞧甩,春花似錦、人聲如沸弥鹦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至朦促,卻和暖如春膝晾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背务冕。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工血当, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人禀忆。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓臊旭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親箩退。 傳聞我的和親對象是個殘疾皇子离熏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 1. 環(huán)境準(zhǔn)備 A. GCC 在控制臺中輸入 如果提示命令未找到,那么說明你的計算機中還沒有g(shù)cc乏德,去安裝一個吧,...
    Chole121閱讀 1,354評論 1 9
  • 小編費力收集:給你想要的面試集合 1.C++或Java中的異常處理機制的簡單原理和應(yīng)用吠昭。 當(dāng)JAVA程序違反了JA...
    八爺君閱讀 4,587評論 1 114
  • 一. Java基礎(chǔ)部分.................................................
    wy_sure閱讀 3,810評論 0 11
  • Java Native Interface (JNI)是一個本地編程接口喊括,可以讓Java代碼使用以其他語言(C/C...
    wangdy12閱讀 7,135評論 0 4
  • 無論是魏國的改革,還是秦國的變法矢棚,都使得各自國家的國力有了大幅度的提升郑什,走向了霸主的地位,然而戰(zhàn)國時期影響最廣成效...
    懶蟲小獅子閱讀 141評論 0 0