这是我第一次尝试将c#与非托管C ++混合使用,所以这可能是一个非常简单的问题,但我不明白。
我需要将C ++ dll中的一些函数调用到C#代码中。这是dll项目的代码:
.h文件:
#pragma once
#include <iostream>
#if defined FIRSTDLL_EXPORTS
#define DECLDIR __declspec(dllexport)
#else
#define DECLDIR __declspec(dllimport)
#endif
extern "C"
{
DECLDIR int Add( int a, int b );
DECLDIR void Function( void );
}
.cpp文件
#include "stdafx.h"
#include "myFct.h"
#include <iostream>
extern "C"
{
DECLDIR int Add( int a, int b )
{
return( a + b );
}
DECLDIR void Function( void )
{
std::cout << "DLL Called!" << std::endl;
}
}
我为debug和releas编译了这个,并将它复制到我的C#项目的debug
文件夹中。这两个版本都没有用。
这是c#代码:
[DllImport("firstDLL.Dll")]
public static extern int Add(int a, int b);
var cyu = Add(3, 5);
当我尝试运行时,我得到了
“托管调试助手'PInvokeStackImbalance'在'C:\ Program Files \ Microsoft Office \ Office14 \ WINWORD.EXE'中检测到问题。 附加信息:调用PInvoke函数'MyAddin!MyAddin.ThisAddIn :: Add'使堆栈失去平衡。这很可能是因为托管PInvoke签名与非托管目标签名不匹配。检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。“
但是我看到签名是一样的。我错过了什么?
谢谢!
答案 0 :(得分:7)
DLLImport的默认调用约定是stdcall,但是C ++代码的默认值是cdecl。您看到的错误消息是调用约定不匹配时显示的内容。这两个调用约定的参数堆栈清理要求是不同的,P / Invoke marshaller检测并报告这个。
修复方法是让您的呼叫约定匹配。
例如,您可以像这样更改P / Invoke:
[DllImport("firstDLL.Dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int Add(int a, int b);
另一种选择是改变你的C ++:
#if defined FIRSTDLL_EXPORTS(returntype)
#define DECLDIR __declspec(dllexport) returntype __stdcall
#else
#define DECLDIR __declspec(dllimport) returntype __stdcall
#endif
显然你应该只做其中一个。如果您同时更改C#和C ++,则反向会遇到同样的问题!
如果我是你,我会将C ++代码保留为cdecl并更改C#以匹配。