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

时间:2010-02-20 20:09:45

标签: c# windows dll pinvoke dllimport

我编写了一个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签名的调用约定和参数是否与目标非托管签名匹配。

3 个答案:

答案 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 );