将C DLL包含到C#中时,对PInvoke函数的调用会使堆栈不平衡

我已经写了一个C DLL和一些C#代码来testing包括这个DLL并执行它的函数。 我不太熟悉这个过程,每当我从C#源代码调用DLL函数时,都会收到一个PInvokeStackImbalanceexception。 代码如下(我已经评论了大部分代码来隔离这个问题):

C#包含代码:

using System; using System.Runtime.InteropServices; using System.IO; namespace TestConsoleGrids { class Program { [DllImport("LibNonthreaded.dll", EntryPoint = "process")] public unsafe static extern void process( long high, long low); static void Main(string[] args) { System.Console.WriteLine("Starting program for 3x3 grid"); process( (long)0, (long)0 ); System.Console.ReadKey(); } } } 

C ++ DLL函数代码

 extern "C" __declspec(dllexport) void process( long high, long low ); void process( long high, long low ) { // All code commented out } 

Visual Studio生成的dllmain代码(我不明白这个构造,所以我包括它)

 // dllmain.cpp : Defines the entry point for the DLL application. #include "stdafx.h" BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } 

例外的细节是:

对PInvoke函数“TestConsoleGrids!TestConsoleGrids.Program :: process”的调用使堆栈不平衡。 这很可能是因为托pipePInvoke签名与非托pipe目标签名不匹配。 检查PInvoke签名的调用约定和参数是否与目标非托pipe签名相匹配。

调用约定是错误的。 如果删除int参数不会触发MDA,那么它是Cdecl:

  [DllImport("LibNonthreaded.dll", CallingConvention = CallingConvention.Cdecl)] public static extern void process(int high, int low); 

这不是导出DLL函数的标准调用约定,如果可以的话,可以考虑在C / C ++代码中进行更改。

在C ++中, long是32位。 在C#中是64位。 在你的C#声明中使用int

您也可以尝试将__stdcall添加到C ++函数。 请参阅: 什么是__stdcall?

在C#中long表示64位int,而在C ++中long表示32位int,则需要将您的pinvoke声明更改为

  [DllImport("LibNonthreaded.dll", EntryPoint = "process")] public unsafe static extern void process( int high, int low); 

您也可以尝试将您的C ++声明更改为stdcall,这是Windows环境中大多数导出函数使用的调用约定。

  __stdcall __declspec(dllexport) void process( long high, long low );