首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 呼叫非受控動態連結庫 (DLL) 函數完整教學

     編輯:關於C#

C# 應用程式若需重用 C/C++ 撰寫的非受控 DLL,可透過 P/Invoke(Platform Invocation Services)機制實現。本文以建立簡單的 add 函數 DLL 為例,完整示範從 C++ 建立 DLL 到 C# 呼叫的全流程。

1. 建立非受控 DLL (C++ 程式碼)

關鍵在於使用 extern "C" 與 __declspec(dllexport) 避免名稱修飾,確保匯出函數名稱保持為 "add"。

// MyLib.cpp
extern "C" __declspec(dllexport) int add(int a, int b);

int add(int a, int b)
{
    return a + b;
}

2. 編譯產生 DLL

使用 Visual C++ 命令列工具 cl.exe,參數 /LD 表示產生動態連結庫:

cl /LD MyLib.cpp

成功後會在目錄下產生 MyLib.dll、MyLib.lib、MyLib.obj、MyLib.exp。

3. C# 專案呼叫 DLL

引用 System.Runtime.InteropServices 命名空間,使用 DllImport 屬性宣告外部函數簽章:

using System;
using System.Runtime.InteropServices;

public class InvokeDll
{
    [DllImport("MyLib.dll", CharSet = CharSet.Auto)]
    public static extern int add(int a, int b);

    public static void Main()
    {
        Console.WriteLine(add(10, 30)); // 輸出 40
    }
}

編譯:csc InvokeDll.cs,執行前確保 MyLib.dll 位於可執行檔同目錄或系統 PATH 路徑下。

常見錯誤與解決

  • EntryPointNotFoundException:若 C++ 端未加 extern "C",編譯器會修飾函數名稱(如 ?add@@YAHHH@Z),導致 C# 找不到 "add" 入口點。務必加上 extern "C"。
  • 呼叫慣例不符:預設為 CallingConvention.Winapi(x86 為 StdCall,x64 為快速呼叫)。若 C++ 端使用 __cdecl,需在 DllImport 指定 CallingConvention = CallingConvention.Cdecl。
  • 資料封送:基本型別(int、double 等)自動封送;指標、結構、字串等複雜型別需額外使用 MarshalAs、IntPtr、StringBuilder 等處理。

延伸議題

若 DLL 匯出函數未使用 extern "C",可嘗試以修飾後的名稱(透過 dumpbin /exports MyLib.dll 取得)搭配 EntryPoint 參數呼叫,但不建議長期依賴。更複雜的參數型別(指標、陣列、結構體、回呼函數)封送技巧,將於後續文章深入探討。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved