windows 如何从 C# 调用 C++ dll 导出函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5367515/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 16:27:42  来源:igfitidea点击:

how to call a C++ dll exported function from c#

c#.netc++windowspinvoke

提问by ghet

This is the first time I'm trying to mix c# an unmanaged C++ so this might be a very simple question , but I don't get it.

这是我第一次尝试将 c# 与非托管 C++ 混合使用,所以这可能是一个非常简单的问题,但我不明白。

I need to call some functions from a C++ dll into C# code. Here is the code for the dll project:

我需要将一些函数从 C++ dll 调用到 C# 代码中。这是dll项目的代码:

the .h file :

.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 );
    }

the .cpp file

.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;
      }
}

I compiled this for both the debug and releas and copied it in the debugfolder of my C# project. Neither version worked.

我为调试和版本编译了这个,并将它复制debug到我的 C# 项目的文件夹中。两个版本都没有工作。

Here is the c# code:

这是 C# 代码:

[DllImport("firstDLL.Dll")]
public static extern int Add(int a, int b);


var cyu = Add(3, 5);

And when I try to run this I get

当我尝试运行它时,我得到

"Managed Debugging Assistant 'PInvokeStackImbalance' has detected a problem in 'C:\Program Files\Microsoft Office\Office14\WINWORD.EXE'. Additional Information: A call to PInvoke function 'MyAddin!MyAddin.ThisAddIn::Add' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature."
“托管调试助手‘PInvokeStackImbalance’在‘C:\Program Files\Microsoft Office\Office14\WINWORD.EXE’中检测到问题。附加信息:对 PInvoke 函数‘MyAddin!MyAddin.ThisAddIn::Add’的调用使堆栈。这可能是因为托管 PInvoke 签名与非托管目标签名不匹配。检查 PInvoke 签名的调用约定和参数是否与目标非托管签名匹配。”

But as I see the signatures are the same. What am I missing??

但正如我所见,签名是一样的。我错过了什么??

Thanks!

谢谢!

回答by David Heffernan

The default calling convention for DLLImport is stdcall, but the default of your C++ code is cdecl. The error message you have seen is what is shown when the calling conventions don't match. The parameter stack cleanup requirements are different for these two calling conventions, and the P/Invoke marshaller detects and reports this.

DLLImport 的默认调用约定是 stdcall,但 C++ 代码的默认调用约定是 cdecl。您看到的错误消息是调用约定不匹配时显示的内容。这两种调用约定的参数堆栈清理要求不同,P/Invoke marshaller 会检测并报告这一点。

The fix is to make your calling conventions match.

解决方法是使您的调用约定匹配。

For example you could change your P/Invoke like so:

例如,您可以像这样更改您的 P/Invoke:

[DllImport("firstDLL.Dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int Add(int a, int b);

The other option is to change your C++:

另一种选择是更改您的 C++:

#if defined FIRSTDLL_EXPORTS(returntype)
    #define DECLDIR __declspec(dllexport) returntype __stdcall
#else
    #define DECLDIR __declspec(dllimport) returntype __stdcall
#endif

Clearly you should only do one of these. If you change both C# and C++ you'll have the same problem in reverse!

显然,您应该只执行其中之一。如果您同时更改 C# 和 C++,您将反过来遇到同样的问题!

If I were you I would leave the C++ code as cdecl and change the C# to match.

如果我是你,我会将 C++ 代码保留为 cdecl 并更改 C# 以匹配。