FB(S1C1): PInvokeStackImbalance对PInvoke函数的调用导致堆栈不对称
FB(S1C1): PInvokeStackImbalance对PInvoke函数的调用导致堆栈不对称
问题:
C#语言 对 C语言 导出函数进行调用时报出的错误.
方案:
设置调用约定CallingConvention的枚举值中的CallingConvention.Cdecl.
实施:
C语言导出函数形式
extern "C" __declspec(dllexport) int Foo(char* pArg);
C#语言调用形式之一
[DllImport("Foo.dll", CallingConvention = CallingConvention.Cdecl)] static extern int Foo(IntPtr pArg);
注:
上述Foo.dll在操作系统环境搜索路径内.
C#语言调用形式之二
1.声明相关加载动态库和获取调用函数
/// <summary> /// a.加载动态库 /// </summary> [DllImport("kernel32.dll", EntryPoint = "LoadLibrary", CallingConvention = CallingConvention.StdCall)] static extern IntPtr LoadLibrary(string strFileName); /// <summary> /// b.获取动态库中函数指针 /// </summary> [DllImport("kernel32.dll", EntryPoint = "GetProcAddress", CharSet = CharSet.Ansi)] static extern IntPtr GetProcAddress(IntPtr pModule, string strFuncName); /// <summary> /// c.释放动态库 /// </summary> [DllImport("kernel32.dll", EntryPoint = "FreeLibrary", CallingConvention = CallingConvention.StdCall)] static extern int FreeLibrary(IntPtr pModule);
2.声明调用指定函数的委托
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] delegate int Foo(IntPtr pArg);
3.使用上述声明函数及委托
void FooCall() { //1 IntPtr pFooDLL = LoadLibrary("Foo.dll"); if (IntPtr.Zero != pFooDLL) { //2 IntPtr pFoo = GetProcAddress(pFooDLL, nameof(Foo)); if (IntPtr.Zero != pFoo) { //Foo Foo funcFoo = (Foo)Marshal.GetDelegateForFunctionPointer(pFoo, typeof(Foo)); if (null != funcFoo) { IntPtr pArg = Marshal.StringToCoTaskMemAnsi("Args"); int iReturn = funcFoo(pArg); } } //3 FreeLibrary(pFooDLL); } }
注:
上述Foo.dll可以在任意指定的系统路径内.