1

可能重复:
对 PInvoke 函数“[…]”的调用使堆栈不平衡

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

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

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

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

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

我在 Windows 7 64 上运行 VS2010。

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

这就是我所做的:

c++ 代码。cp:

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#项目和app c#项目(WPF)的bin/Debug中,并尝试调用

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

1 回答 1

2

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

EXPORT_DLL __stdcall int create(int Handle);

在您的 C# 项目中:

[DllImport(SHADOW_DLL_NAME, CallingConvention = CallingConvention.StdCall)]
于 2012-05-15T14:51:02.690 回答