C#調(diào)用Java
將jar轉(zhuǎn)換為dll
具體步驟 :下載一個(gè) IKVM 配置好環(huán)境變量 具體操作如下
一、將已經(jīng)編譯后的java中Class文件進(jìn)行打包;打包命令JAR
- 此處 java的所有類必須放在一個(gè)Package中,不要使用缺省的包,C#會(huì)找不到類之間的調(diào)用(C#貎似不能引用其它dll里的默認(rèn)namespace里邊的內(nèi)容,所以java文件必須聲明包,以便被轉(zhuǎn)換成命名空間。此外,因?yàn)?java中默認(rèn)訪問權(quán)限的方法會(huì)被轉(zhuǎn)換成internal方法,所以在java中必須將這些方法顯式地聲明為public),需要自己建,我用的是eclipse,寫完程序直接導(dǎo)出成jar文件。
另外現(xiàn)在這個(gè)版本好像不支持Java 圖形界面,反正我調(diào)試時(shí),一旦new一個(gè)控件,C#就說此方法未被實(shí)現(xiàn)什么的。
- 也可以使用命令:jar cvf test.jar -C com/ .
其中test.jar為要生成的jar包;com/ . 為指定的當(dāng)前目錄下的文件夾,該文件夾包括子文件夾及class文件;
二、到IKVM官方網(wǎng)站下載IKVM需要的組件 http://www.ikvm.net/
ikvmbin-0.44.0.5.zip
三、設(shè)置路徑
解壓ikvmbin-0.44.0.5.zip ,并將%IKVM_HOME%\bin添加到path中。此處的%IKVM_HOME%是指解壓后ikvm的主目錄。
四、將java的jar包轉(zhuǎn)換為.dll控件
使用的命令:ikvmc -out:IKVM.dll test.jar (整個(gè)操作這個(gè)是主要的。)
其中IKVM.dll為將要生成的.dll控件文件名;test.jar(盡量添加上文件的路徑)為之前打包好的jar包文件。(寫的時(shí)候盡量添加文件的路徑名稱,便于查找生成后的dll文件 )
現(xiàn)在dll文件已經(jīng)成功了,但是后面還有運(yùn)用這個(gè)dll在添加到C#項(xiàng)目中運(yùn)行的時(shí)候可能會(huì)報(bào)錯(cuò)。這些錯(cuò)誤就是缺少一些IKVMxxxx.dll文件,這些文件都在ikvm-0.46.0.1\bin 文件下可以找到。
五、在C#項(xiàng)目中添加所需的控件
1、新建一個(gè)C#.NET項(xiàng)目,首先添加一下必須的DLLs (references中Add reference,然后Browse找到dll)
%IKVM_HOME%\bin\IKVM.OpenJDK.Core.dll
%IKVM_HOME%\bin\IKVM.Runtime.dll
%IKVM_HOME%\bin\IKVM.Runtime.JNI.dll
2、添加已生成的.dll文件
將之前生成好的.dll文件加載到C#項(xiàng)目中
六、測(cè)試
在C#項(xiàng)目中使用java類,其方法同java。首先用using 包名,這樣才能找到類
Java使用jna調(diào)用c#中的dll
一、原理說明:
因?yàn)閏#代碼是托管到.net平臺(tái)上的,所以java不能直接調(diào)用c#代碼,于是引入C++中間件,c++項(xiàng)目可以設(shè)置項(xiàng)目為clr公共運(yùn)行時(shí),從而通過引用的方式調(diào)用c#相應(yīng)方法。而jna是可以直接調(diào)用c++生成的dll的,于是大致流程就走通了。c++調(diào)用寫好的c#dll,java再調(diào)用c++生成的dll中間件,大致流程就是這樣了,不過其中有很多坑,下面我會(huì)細(xì)說。
二、運(yùn)行平臺(tái):
系統(tǒng):Windows 10 x64
開發(fā)工具:Visual Studio 2015/2017(我筆記本和公司電腦安裝不同版本,我都有實(shí)現(xiàn)過) MyEclipse2014
SDK:jdk-x86、jdk-x64 (dll分為x86和x64平臺(tái),和jdk的版本要對(duì)應(yīng),同一臺(tái)電腦裝兩個(gè)版本的jdk比較煩,我采用的是系統(tǒng)配置jdk32位調(diào)試32位dll,然后myeclipse自帶64位jdk調(diào)試64位dll)
三、準(zhǔn)備工作:
1、首先準(zhǔn)備上述運(yùn)行平臺(tái),建議選擇和系統(tǒng)位數(shù)一致的jdk(安裝vs、myeclipse或eclipse或sts);
2、下載jna.jar :JNA下載 (下載jna-4.4.0.jar 和 jna-platform-4.4.0),也可以 本地下載
四、開始CODE
1. 生成c#DLL
(一)以管理員方式啟動(dòng)vs(項(xiàng)目涉及到注冊(cè)com組件,必須以管理員啟動(dòng)才能完成),新建c#項(xiàng)目

(二)設(shè)置c#項(xiàng)目
首先,右鍵剛剛新建的Invoke項(xiàng)目,點(diǎn)擊屬性。

繼續(xù)設(shè)置項(xiàng)目屬性。

記得保存。
然后新建需要被調(diào)用的CSharp類代碼。這里我們新建一些簡(jiǎn)單的方法,為了演示效果我們分別對(duì)int、string、bool進(jìn)行操作。如圖:

然后右鍵項(xiàng)目,點(diǎn)擊生成。

第一步,完成,干得漂亮。
2. 生成c++中間件
(一)新建c++項(xiàng)目并設(shè)置屬性



項(xiàng)目新建成功,右鍵項(xiàng)目,選擇屬性。


(二)書寫c++代碼
添加cpp文件


編輯cpp文件
好了,c++和c#全部工作完成,右鍵生成。

復(fù)制下dll生成文件全名,一會(huì)兒java里面用。
五、編寫java代碼
1. 新建java project ,注意選擇和dll平臺(tái)一致的jdk。然后將之前下載的兩個(gè)jna的jar加載到項(xiàng)目里面,如圖:

2. 開始寫java 代碼
然后我們運(yùn)行:

哦豁,報(bào)錯(cuò)了【無(wú)效的內(nèi)存訪問】,因?yàn)閖ava找到了c++dll,但是沒找到c#的dll,其中c++dll我們寫的全路徑名,可以直接找到,那么c#的dll怎么找呢。答案是將c#的dll復(fù)制到j(luò)dk的bin目錄下,jvm就能找到了。
如圖我們將Invoke.dll復(fù)制到j(luò)dk的bin目錄下:

然后再運(yùn)行:

nice!對(duì)于常用類型中的int、string、boolean都可以順利傳遞了,事實(shí)上其他類型的也可以實(shí)現(xiàn),只要遵循不同語(yǔ)言之間的類型對(duì)應(yīng)關(guān)系就可以了,具體的類型關(guān)系可以百度。
六、注意事項(xiàng)
1. java報(bào)錯(cuò):Exception in thread "main" java.lang.Error: Invalid memory access
可能原因:
c#dll沒有復(fù)制到j(luò)dk的bin目錄;
java和c++之間數(shù)據(jù)類型不對(duì)應(yīng);
2. java報(bào)錯(cuò):Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable to load library 'D:\vs workplace\X86InvokeTest\Release\X86CPPDlls': Native library (win32-x86/D:\vs workplace\X86InvokeTest\Release\X86CPPDlls.dll) not found in resource path ([file:/G:/My%20Eclipse%20workplace/InvokeCSharpX86Test/bin/, file:/G:/My%20Eclipse%20workplace/InvokeCSharpX86Test/Lib/jna-4.4.0.jar, file:/G:/My%20Eclipse%20workplace/InvokeCSharpX86Test/Lib/jna-platform-4.4.0.jar])
可能原因:
c++dll路徑不正確,建議做test時(shí)用絕對(duì)路徑,這樣你在c++項(xiàng)目編譯過后不用拷貝便可以在java程序里面直接調(diào)用;
jdk的平臺(tái)和c++項(xiàng)目的平臺(tái)不匹配,jdk是32位那么c++dll一定也是32位的,64位也同樣;
3. windows64位下編譯的32位dll測(cè)試失敗,暫時(shí)不清楚是不是64位系統(tǒng)的原因,由于我電腦虛擬機(jī)沒有裝上,就沒有去32位系統(tǒng)上測(cè)試了。