如何调用c++ dll从c#导出的函数

时间:2022-09-01 16:40:33

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 debug folder of my C# project. Neither version worked.

我为debug和releas编译了这段代码,并将其复制到c#项目的debug文件夹中。无论是工作版本。

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."

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

但是我看到的签名是一样的。我错过什么呢? ?

Thanks!

谢谢!

1 个解决方案

#1


7  

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封送程序检测并报告这一点。

The fix is to make your calling conventions match.

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

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

例如,您可以这样更改您的P/调用:

[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#更改为匹配。

#1


7  

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封送程序检测并报告这一点。

The fix is to make your calling conventions match.

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

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

例如,您可以这样更改您的P/调用:

[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#更改为匹配。