C#調(diào)用Java
將jar轉(zhuǎn)換為dll
具體步驟 :下載一個 IKVM 配置好環(huán)境變量 具體操作如下
一、將已經(jīng)編譯后的java中Class文件進(jìn)行打包;打包命令JAR
- 此處 java的所有類必須放在一個Package中,不要使用缺省的包,C#會找不到類之間的調(diào)用(C#貎似不能引用其它dll里的默認(rèn)namespace里邊的內(nèi)容,所以java文件必須聲明包,以便被轉(zhuǎn)換成命名空間。此外,因為 java中默認(rèn)訪問權(quán)限的方法會被轉(zhuǎn)換成internal方法,所以在java中必須將這些方法顯式地聲明為public),需要自己建,我用的是eclipse,寫完程序直接導(dǎo)出成jar文件。
另外現(xiàn)在這個版本好像不支持Java 圖形界面,反正我調(diào)試時,一旦new一個控件,C#就說此方法未被實現(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 (整個操作這個是主要的。)
其中IKVM.dll為將要生成的.dll控件文件名;test.jar(盡量添加上文件的路徑)為之前打包好的jar包文件。(寫的時候盡量添加文件的路徑名稱,便于查找生成后的dll文件 )
現(xiàn)在dll文件已經(jīng)成功了,但是后面還有運(yùn)用這個dll在添加到C#項目中運(yùn)行的時候可能會報錯。這些錯誤就是缺少一些IKVMxxxx.dll文件,這些文件都在ikvm-0.46.0.1\bin 文件下可以找到。
五、在C#項目中添加所需的控件
1、新建一個C#.NET項目,首先添加一下必須的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#項目中
六、測試
在C#項目中使用java類,其方法同java。首先用using 包名,這樣才能找到類
Java使用jna調(diào)用c#中的dll
一、原理說明:
因為c#代碼是托管到.net平臺上的,所以java不能直接調(diào)用c#代碼,于是引入C++中間件,c++項目可以設(shè)置項目為clr公共運(yùn)行時,從而通過引用的方式調(diào)用c#相應(yīng)方法。而jna是可以直接調(diào)用c++生成的dll的,于是大致流程就走通了。c++調(diào)用寫好的c#dll,java再調(diào)用c++生成的dll中間件,大致流程就是這樣了,不過其中有很多坑,下面我會細(xì)說。
二、運(yùn)行平臺:
系統(tǒng):Windows 10 x64
開發(fā)工具:Visual Studio 2015/2017(我筆記本和公司電腦安裝不同版本,我都有實現(xiàn)過) MyEclipse2014
SDK:jdk-x86、jdk-x64 (dll分為x86和x64平臺,和jdk的版本要對應(yīng),同一臺電腦裝兩個版本的jdk比較煩,我采用的是系統(tǒng)配置jdk32位調(diào)試32位dll,然后myeclipse自帶64位jdk調(diào)試64位dll)
三、準(zhǔn)備工作:
1、首先準(zhǔn)備上述運(yùn)行平臺,建議選擇和系統(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
(一)以管理員方式啟動vs(項目涉及到注冊com組件,必須以管理員啟動才能完成),新建c#項目
(二)設(shè)置c#項目
首先,右鍵剛剛新建的Invoke項目,點擊屬性。
繼續(xù)設(shè)置項目屬性。
記得保存。
然后新建需要被調(diào)用的CSharp類代碼。這里我們新建一些簡單的方法,為了演示效果我們分別對int、string、bool進(jìn)行操作。如圖:
然后右鍵項目,點擊生成。
第一步,完成,干得漂亮。
2. 生成c++中間件
(一)新建c++項目并設(shè)置屬性
項目新建成功,右鍵項目,選擇屬性。
(二)書寫c++代碼
添加cpp文件
編輯cpp文件
好了,c++和c#全部工作完成,右鍵生成。
復(fù)制下dll生成文件全名,一會兒java里面用。
五、編寫java代碼
1. 新建java project ,注意選擇和dll平臺一致的jdk。然后將之前下載的兩個jna的jar加載到項目里面,如圖:
2. 開始寫java 代碼
然后我們運(yùn)行:
哦豁,報錯了【無效的內(nèi)存訪問】,因為java找到了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!對于常用類型中的int、string、boolean都可以順利傳遞了,事實上其他類型的也可以實現(xiàn),只要遵循不同語言之間的類型對應(yīng)關(guān)系就可以了,具體的類型關(guān)系可以百度。
六、注意事項
1. java報錯:Exception in thread "main" java.lang.Error: Invalid memory access
可能原因:
c#dll沒有復(fù)制到j(luò)dk的bin目錄;
java和c++之間數(shù)據(jù)類型不對應(yīng);
2. java報錯: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時用絕對路徑,這樣你在c++項目編譯過后不用拷貝便可以在java程序里面直接調(diào)用;
jdk的平臺和c++項目的平臺不匹配,jdk是32位那么c++dll一定也是32位的,64位也同樣;
3. windows64位下編譯的32位dll測試失敗,暫時不清楚是不是64位系統(tǒng)的原因,由于我電腦虛擬機(jī)沒有裝上,就沒有去32位系統(tǒng)上測試了。