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 导出的类调用方法。 
由 .NET Compact Framework 支持 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");
    }
}
posted @ 2012-08-10 10:56  你是猴子请的救兵么  阅读(123)  评论(0)    收藏  举报