c#调用c++dll产生托管签名不匹配问题
可能是由于调用方式的问题。 [DllImport("testDll.dll", EntryPoint = "add", ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] 此处CallingConvertion是一个枚举类型,指明垃圾的处理方式,是有调用方还是被调方清理垃圾。默认是stdCal方式,c#需要使用Cdecl方式才可正常使用。下面是微软的msdn Copy.
| 成员名称 | 说明 | |
|---|---|---|
| Cdecl | 调用方清理堆栈。这使您能够调用具有 varargs 的函数(如 Printf),使之可用于接受可变数目的参数的方法。 | |
| FastCall | 不支持此调用约定。 | |
| StdCall | 被调用方清理堆栈。这是使用平台 invoke 调用非托管函数的默认约定。 | |
| ThisCall | 第一个参数是 this 指针,它存储在寄存器 ECX 中。其他参数被推送到堆栈上。此调用约定用于对从非托管 DLL 导出的类调用方法。 | |
![]() |
Winapi | 此成员实际上不是调用约定,而是使用了默认平台调用约定。例如,在 Windows 上默认为 StdCall,在 Windows CE.NET 上默认为 Cdecl。 |
请始终使用 CallingConvention 枚举,而不是 CALLCONV 枚举在托管代码中指定一个调用约定。后者仅作 COM 定义之用。DllImportAttribute 和 System.Reflection.Emit 中的若干类使用 CallingConvention 枚举,以动态发出平台调用签名。
下面的示例演示了如何应用 Cdecl 调用约定,因为由调用方负责清理堆栈,所以必须使用此调用约定。
using System; using System.Runtime.InteropServices; public class LibWrap { // C# doesn't support varargs so all arguments must be explicitly defined. // CallingConvention.Cdecl must be used since the stack is // cleaned up by the caller. // int printf( const char *format [, argument]... ) [DllImport("msvcrt.dll", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)] public static extern int printf(String format, int i, double d); [DllImport("msvcrt.dll", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)] public static extern int printf(String format, int i, String s); } public class App { public static void Main() { LibWrap.printf("\nPrint params: %i %f", 99, 99.99); LibWrap.printf("\nPrint params: %i %s", 99, "abcd"); } }


浙公网安备 33010602011771号