首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C# 動態加載 C++ DLL 時 PInvokeStackImbalance 錯誤解決

     編輯:程式設計綜合問答

問題現象

靜態 DllImport 調用 C++ DLL 正常,但動態加載(LoadLibrary + GetProcAddress + Marshal.GetDelegateForFunctionPointer)報 PInvokeStackImbalance:托管簽名與非托管目標簽名不匹配,調用約定或參數不一致。

根本原因

C# 委托默認調用約定為 StdCall,而 C++ DLL 導出函數默認 Cdecl。靜態 DllImport 可通過 CallingConvention.Cdecl 指定,但動態委托需顯式標記。

解決方案

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate int FUNC1(string xmlSta, StringBuilder fileOut);

完整修正代碼片段

public static class NativeMethod {
    [DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]
    public static extern IntPtr LoadLibrary(string lpLibFileName);
    [DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
    public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
    [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
    public static extern bool FreeLibrary(IntPtr hModule);
}

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate int FUNC1(string xmlSta, StringBuilder fileOut);

class Program {
    static void Main() {
        StringBuilder sbr = new StringBuilder(10);
        IntPtr hModule = NativeMethod.LoadLibrary(@"a.dll");
        if (hModule == IntPtr.Zero) return;
        IntPtr procAddr = NativeMethod.GetProcAddress(hModule, "FUNC1");
        FUNC1 cFunc = (FUNC1)Marshal.GetDelegateForFunctionPointer(procAddr, typeof(FUNC1));
        Console.WriteLine(cFunc("abc ", sbr));
        NativeMethod.FreeLibrary(hModule);
        Console.Read();
    }
}

注意事項

  • 委托簽名必須與 C++ 導出函數完全一致:參數類型、調用約定、返回類型。
  • StringBuilder 對應 char* 輸出緩衝區,需預分配足夠容量。
  • 優先使用 IntPtr 而非 int 接收句柄,兼容 64 位進程。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved