1. 程式人生 > >利用jna呼叫使用C#的dll檔案

利用jna呼叫使用C#的dll檔案

目前所做java專案中有部分模組需要使用客戶提供的dll動態庫檔案中封裝的演算法,客戶提供了一個dll檔案以及C#語言編寫的可執行檔案例項,演算法具體程式碼未提供。之前只涉及過利用jna呼叫c++所生成的dll檔案,最終的目的則是需要java呼叫C#生成的dll檔案。

       本人涉及dll的封裝操作不是很久,暫時未能找到java利用jna呼叫C#生成的dll的更有效方法,於是採用一種變通的方法。

       這種方法的思路是:c++專案設定為clr公共執行時,可以通過引用的方法呼叫C#相應方法,java可以通過jna呼叫c++生成的dll,所以首先需要將C#的dll封裝成c++的dll,再通過jna呼叫封裝好的c++的dll檔案。

工具:vs2010

首先,生成C#的dll檔案。

客戶給的dll檔案是直接由C#生成的,如果熟悉這dll檔案的內部結構則可直接略過此步驟。因為客戶給的dll名稱空間不夠明確,並且其中有兩個相似的類,而每個類下又有功能相同且名稱相同的幾個方法,為了能夠明確呼叫給定的C#的dll動態庫檔案中的方法,同時為了c++呼叫方便,這裡是將客戶給的dll檔案利用C#重新封裝了一層。步驟如下。

1)     開啟vs2010,新建專案,選擇C#語言下的“類庫”,填寫專案名稱。

2)     在生成專案上右擊設定專案屬性,點選“程式集資訊”,勾選“使程式集COM可見”,點選確定。

3)     設定“生成”屬性,勾選“為COM互操作註冊”,儲存設定。

4)     在專案的“引用”中新增客戶提供的dll檔案。

5)     新增必須的C#程式碼。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

using QiJuSiChu.SpeechLib;//新增引用的dll名稱
namespace PackLib
{
    public class Class1
    {
        acelp_cn_8k lpc8k;  //引用的dll中的演算法的例項
        public void dealVoiceToPcm(string voicePath, int curgainshift)
        {
            lpc8k = new acelp_cn_8k();
            lpc8k.Initialize();//初始化
            lpc8k.SetGainShift(curgainshift);//設定增益

            lpc8k.decodeframe(voicePath);//解碼

        }
        
    }
}

6)     點選生成專案,成功。



其次,使用c++封裝dll檔案。

為了能夠使用jna呼叫C#生成的dll檔案,必須使用c++進行進行一次封裝,這一步驟至關重要。

1)     新建c++專案。


2)     在專案名稱上右擊,設定專案屬性。


3)     在專案名稱上右擊,選擇“引用”,引入之前生成的C#的dll。


4)     新增cpp檔案,書寫必須的c++程式碼。程式碼如下。

#ifdef MYLIBAPI 
#else 
#define  MYLIBAPI  extern "C" __declspec(dllimport)     
#endif 
 
 
MYLIBAPI void DealVoiceToPcm(char *voicePath,int curgainshift); //新增函式宣告,此函式為生成的C++的dll的外部公開函式

 
using namespace System;
using namespace PackLib;//新增引入的C#的dll名稱

 
void DealVoiceToPcm(char *voicePath,int curgainshift)
{
	String ^ paraStr = gcnew String(voicePath);//需要將char *轉換為託管的String型別,否則失敗
    Class1 ^method = gcnew Class1();//例項化C#的類
    method->dealVoiceToPcm(paraStr, curgainshift);//呼叫C#的dll中的方法
    
}

5)     生成專案,成功。

最後,需要使用jna引用新生成的C++的dll檔案,這與一般的jna呼叫dll動態庫檔案的方法一樣,不再贅述。

注:這裡如果將所有的C#及c++的dll檔案放到java專案的目錄下,會出現錯誤,原因是java雖然可以找到c++的dll檔案,但是找不到C#的dll檔案,需要將C#的dll檔案放到執行機器jdk安裝目錄下的bin資料夾下。問題解決。

再次重複一句這些成的dll檔案應當與執行機器上安裝的jdk的版本一致(x86或者x64),否則會出現調用出錯。