包装c ++函数以在C#中使用

时间:2012-05-15 14:40:50

标签: c# c++ pinvoke dllimport

  

可能重复:
  A call to PInvoke function '[…]' has unbalanced the stack

我正在尝试包装一些用c ++编写的函数,以便在c#程序中使用它们(WPF,或者作为一个控制台应用程序的示例),但是获得运行时异常。

我想这是一个编译问题(C#one的c ++项目)。当我更改C#项目的平台目标时,我得到了不同的例外。当平台目标是x64我得到

  

尝试加载格式不正确的程序。 (HRESULT异常:0x8007000B)

当我尝试将其编译为x86时,我得到:

  

对PInvoke函数'Wrapper!Wrapper.IWrapper :: create'的调用使堆栈失衡。这很可能是因为托管PInvoke签名与非托管目标签名不匹配。检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。

我在Windows 7 64上运行VS2010。

对于如何解决这个问题的任何想法都会感到高兴。

这就是我所做的:

c ++代码。 CPP:

int create(int Handle)
{
    return 1;
}

和h:

#define EXPORT_DLL __declspec(dllexport)

extern "C"
{
EXPORT_DLL int create(int Handle);
}

然后在第二个C#项目中,我调用这个dll,其中c ++项目的名称是wrapAttemptC

namespace Wrapper
{
    internal class IWrapper
    {
        const string SHADOW_DLL_NAME = "wrapAttemptC.dll";

        [DllImport(SHADOW_DLL_NAME)]
        public static extern int create(int Handle);
    }
    public class CWW
    {
        public CWW(){}

        public int Connect(int cam)
        {
            return IWrapper.create(cam);
        }
    }
}

然后,我将c ++项目中创建的DLL文件放在此c#项目的bin / Debug和app c#project(WPF)中,并尝试调用

CWW cww = new CWW();
cww.Connect(5);

1 个答案:

答案 0 :(得分:2)

C ++导出函数的默认调用约定为cdecl,但DllImport属性的默认调用约定为WinApi(默认为stdcall)。所以你在那里有一个不匹配,可能会弄乱你的堆栈。尝试在DllImport属性,C ++函数声明或更好的两者中明确地声明调用约定(以便它们匹配)。像这样:

EXPORT_DLL __stdcall int create(int Handle);

在你的C#项目中:

[DllImport(SHADOW_DLL_NAME, CallingConvention = CallingConvention.StdCall)]