在C#中使用C/C++寫的DLL (轉)

worldblog發表於2007-12-14
在C#中使用C/C++寫的DLL (轉)[@more@]

在中使用C/C++寫的DLL

呵呵..,又到了我有想寫點東西的時候了.最近在論壇老是看見有朋友問

C/C++的如何在C#中使用?其實這是個很不錯的想法.程式碼複用.不過

託管程式如何使用非託管程式碼呢?想想看,很自然就聯想到了DLL動態連線庫

把C/C++的程式碼編譯成DLL,然後使用,這裡我假設我的C/C++程式碼裡包含一個

,叫average(int av[])

申明如下:
extern "C" __declspec(dllexport) __cdecl int average(int *av);

實現嘛就更簡單了
__declspec(dllexport) __cdecl int average(int av[])
{
int i=0;
int sum=0;
  while(av)
{
  sum+=av[i];
  i++;
}
return sum/i;
}//隨手寫的也許有點問題

好了不管那麼多,讓我們來看看C#的程式碼是如何實現的,我想你應該想的到

是什麼?猜猜看,OK,我想你至少能想到兩個英文單詞dll import,是的你猜對了

DLLImport 屬性,就是它,看看它有些什麼,我可以用到,MSDN是最好的選擇.看見了嗎

是的,準確地說,DllImport 屬性具有下列行為:

它只能放置在方法宣告上。

它具有單個定位引數:指定包含被匯入方法的 dll 名稱的 dllName 引數。

它具有五個命名引數:
 

CallingConvention 引數指示入口點的約定。如果未指定 CallingConvention,則使用預設值
CallingConvention.Win。

CharSet 引數指示用在入口點中的字符集。如果未指定 CharSet,則使用預設值 CharSet.Auto。

EntryPoint 引數給出 dll 中入口點的名稱。如果未指定 EntryPoint,則使用方法本身的名稱。

ExactSpelling 引數指示 EntryPoint 是否必須與指示的入口點的拼寫完全匹配。如果未指定
ExactSpelling,則使用預設值 false。

PreserveSig 引數指示方法的簽名應當被保留還是被轉換。當簽名被轉換時,它被轉換為一個具有
HRESULT 返回值和該返回值的一個名為 retval 的附加輸出引數的簽名。如果未指定 PreserveSig,則使
用預設值 true。

SetLastError 引數指示方法是否保留 “上一錯誤”。如果未指定 SetLastError,則使用預設值

false。

它是一次性屬性類。

此外,用 DllImport 屬性修飾的方法必須具有 extern 修飾符。

是的,上面就是MSDN原文內容.好了繼續我們的例子,好了,先把我們上面的C程式碼編譯成DLL

叫什麼呢?那就叫MYDLLTest好了.

[DllImport("MYDLLTest.dll",EntryPoint="average",ExactSpelling=false,CallingConvention=CallingConvention.Cdecl)]
static extern int average(int av[]);

好了,該是你找個地方寫一句的時候了

如:

int[5] i={1,2,3,4,5};
int j=average(i);

 


好了,你看到了,就是這樣的,可是事實上並沒有你想的那麼簡單.因為設計到很多問題

你看上面的例子中,int是在C#和C/C++中都有的,可是如果是char *呢?也許你會說string

可是你看在C/C++中這些都表示字串(char*,or wchar_t*,or BSTR, ..)那我們該怎麼辦?

想想看,還有些什麼?屬性嗎?是的,找找,對了我似乎想到一個單詞.Marshal恩..記得它嗎?

別告訴我,你會把它拼成馬歇爾.哈哈..開個玩笑是列集.我們在MSDN上輸入看看找到什麼了?

是的MarshalAs.看看MSDN上說些什麼?"指示應如何在託管程式碼和非託管程式碼之間封送資料"

哈哈.看來不錯呢.在看看下面的備註:

可將該屬性應用於引數、欄位或返回值。

該屬性為可選屬性,因為每個資料型別都有預設的封送處理行為。僅在可以將給定型別封送到多個型別時需要此屬性。例如,String 可能作為 LPStr、LPWStr、LPTStr 或 BStr 封送到非託管程式碼。預設情況下,字串作為 BStr 封送到 方法。可將 MarshalAsAttribute 屬性應用於個別的欄位或引數,以使該字串作為 LPStr 而非 BStr 封送。有關如何使用此屬性的完整詳細資訊,請參閱“資料封送處理規範”。

大多數情況下,該屬性只是使用 UnmanagedType 列舉標識非託管資料的格式,如下面的示例所示。

[C#]
void MyMethod([MarshalAs(LPStr)] String s);
某些 UnmanagedType 列舉需要附加資訊。例如,當 UnmanagedType 為 LPArray 時需要附加資訊。有關如何使用此屬性的完整說明,請參閱“資料封送處理規範”。

瞧見了,正是我們需要的對嗎?好了,我就寫怎麼多了,事實上,還有關於結構(struct)的

這就需要,你來完成了.希望對你有點幫助.(完)


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-993061/,如需轉載,請註明出處,否則將追究法律責任。

相關文章