Вызов функции PInvoke разбалансирует стек при включении C DLL в C # - PullRequest
3 голосов
/ 20 февраля 2010

Я написал C DLL и некоторый C # код для тестирования, включая эту DLL и выполнение функций из нее. Я не слишком знаком с этим процессом и получаю исключение PInvokeStackImbalance всякий раз, когда моя функция DLL вызывается из исходного кода C #. Код выглядит следующим образом (я выделил большую часть кода, чтобы изолировать эту проблему):

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 ]

5 голосов
/ 21 февраля 2010

Соглашение о вызовах неверно. Если удаление аргументов int не приводит к отключению MDA, это Cdecl:

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

Это не стандартное соглашение о вызовах для экспортируемых функций DLL, вы можете изменить его в коде C / C ++, если можете.

2 голосов
/ 20 февраля 2010

В C ++ long является 32-битным. В C # это 64 бит. Используйте int в вашей декларации C #.

Вы также можете попробовать добавить __stdcall в функцию C ++. См .: Что такое __stdcall?

0 голосов
/ 20 февраля 2010

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