靜態 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();
}
}
StringBuilder 對應 char* 輸出緩衝區,需預分配足夠容量。IntPtr 而非 int 接收句柄,兼容 64 位進程。