C 中呼叫 除錯C 的DLL

2021-05-22 16:21:58 字數 3440 閱讀 4221

被c#呼叫的dll一般只需要把匯出的函式 以適當的形式呈現即可呼叫,比如

extern "c" __declspec(dllexport)

bool integrate3 (),這樣的函式,在c#裡面宣告如:

[dllimport("***.dll", callingconvention = callingconvention.stdcall, charset = charset.unicode)]

public static extern bool integrate3();,這裡的呼叫相對是簡單的,而有些資料型別則必須通過marshalas來做託管型別的轉換,如:

extern "c" __declspec(dllexport)

bool integrate (lpcwstr file1, lpcwstr file2, lpcwstr outputfile)

由於資料型別不一致,所以在宣告時要注意把型別轉換過來。

[dllimport("***.dll", callingconvention = callingconvention.stdcall, charset = charset.unicode)]

public static extern bool integrate([in, marshalas(unmanagedtype.lpwstr)]string file1,

[in, marshalas(unmanagedtype.lpwstr)]string file2, [in, marshalas(unmanagedtype.lpwstr)]string outputfile);

這樣呼叫基本是沒有問題,重點在於資料型別的轉換。多試過幾次了就不問題了。

另外乙個小小的實踐經驗就是在c#中除錯c++的dll,知道了就是一句話,不知道就要搞半天,在c#專案屬性中「啟用除錯項」中一項:「啟用非託 管**除錯」,鉤上這個,就萬事大吉了,就像你除錯一般的程式一樣。

c#呼叫c++的dll時,引數傳遞便成了乙個問題。今天我碰到的乙個問題是,在c++中匯出的函式的引數是string型別的,在c#中通過 string的引數呼叫時,便會出現該記憶體已損壞或不能讀取的異常資訊。後來我把c++的匯出函式的引數由string改為lptstr型別,也即 char*型別,然後在c#中對應的引數改為stringbuilder型別,既解決了傳進去的引數問題,又解決了傳出引數的問題。

dllimport知識拓 展:dllimport 

.net 框架程式可以通過靜態 dll 入口點的方式來訪問本機**庫。dllimport 屬性用於指定包含外部方法的實現的dll 位置。

dllimport 屬性定義如下:

namespace system.runtime.interopservices

public callingconvention callingconvention;

public charset charset;

public string entrypoint;

public bool exactspelling;

public bool preservesig;

public bool setlasterror;

public string value }

} }

說明:

1、dllimport只能放置在方 法宣告上。 

2、dllimport具有單個定位引數:指定包含被匯入方法的 dll 名稱的 dllname 引數。 

3、 dllimport具有五個命名引數:

a、callingconvention 引數指示入口點的呼叫約定。如果未指定 callingconvention,則使用預設值 callingconvention.winapi。

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

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

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

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

f、setlasterror 引數指示方法是否保留 win32"上一錯誤"。如果未指定 setlasterror,則使用預設值 false。 

4、它是一次性屬性類。

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

//通過dllimport引用user32.dll類。messagebox來自於user32.dll類

[dllimport("user32.dll", entrypoint="messagebox")]

public static extern int messagebox(int hwnd, string strmessage, string strcaption, uint uitype);

public static void main() }

物件導向的程式語言幾乎都用到了抽象類這一概念, 抽象類為實現抽象事物提供了更大的靈活性。c#也不例外, c#通過覆蓋虛介面的技術深化了抽象類的應用。欲瞭解這方面的知識,請看下一節-覆蓋虛介面

這裡講述的是c#呼叫標準動態庫的問題, 在我以前的檔案中講到過, c#呼叫win32api, 原理是一樣的. 這裡我詳細講解用c寫乙個標準的動態庫, 然後讓c#呼叫. (本篇適合初學者, 中間沒有任何冗餘**, 簡潔明瞭)

軟體環境: vc6.0(當然其他版本的vc5也可以)

1.製作標準動態庫

__declspec(dllexport) int __cdecl add(int, int);//這一句是宣告動態庫輸出乙個可供外不呼叫的函式原型.

int add(int a,int b)

/out:mylib.dll

/dll

/implib:mylib.lib

mylib.obj

creating library mylib.lib and object mylib.exp

確信有以上輸出, 說明編譯成功生成了動態庫.

2.編寫c-sharp程式呼叫該動態庫

using system;

using system.runtime.interopservices;//這是用到dllimport時候要引入的包

public class invokedll

}保 存為invokedll.cs檔案, 與mylib.dll置於同一目錄, 編譯該檔案.

h:/xschool/c#-school/howto>csc invokedll.cs

將生成invokedll.exe, 可以執行該檔案.

ps:原文

C 中呼叫 C 編寫的 dll 的 除錯

以下只是針對vs2005,其他版本沒試過 前提 必須有該dll 的c 原始碼 斷點處 被執行 c 程式呼叫c 寫的dll 1.確保工程為debug,而不是release 2.將該dll設為啟動項 3.設定該dll的屬性,property debugging debugger type 為 nativ...

在c 中呼叫並除錯C 的DLL

被c 呼叫的dll一般只需要把匯出的函式以適當的形式呈現即可呼叫,比如 extern c declspec dllexport bool integrate3 這樣的函式,在c 裡面宣告如 dllimport dll callingconvention callingconvention.stdca...

C 中除錯C 的Dll

被c 呼叫的dll一般只需要把匯出的函式以適當的形式呈現即可呼叫,比如 extern c declspec dllexport bool integrate3 這樣的函式,在c 裡面宣告如 dllimport dll callingconvention callingconvention.stdca...