我编写了一个C DLL和一些C#代码来测试包含这个DLL并从中执行函数。我对这个过程并不太熟悉,每当从C#源代码调用DLL函数时,我都会收到PInvokeStackImbalance异常。代码如下(我已经注释了大多数代码来隔离这个问题):
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'的调用使堆栈失衡。这很可能是因为托管PInvoke签名与非托管目标签名不匹配。检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。
答案 0 :(得分:5)
调用约定是错误的。如果删除int参数不会使MDA跳闸,那么它就是Cdecl:
[DllImport("LibNonthreaded.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void process(int high, int low);
这不是导出的DLL函数的标准调用约定,如果可以的话,您可以考虑在C / C ++代码中更改它。
答案 1 :(得分:2)
在C ++中,long
是32位。在C#中它是64位。在C#声明中使用int
。
您也可以尝试将__stdcall
添加到C ++函数中。请参阅:What is __stdcall?
答案 2 :(得分:0)
在C#中long
表示64位int,而在C ++中表示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 );