2010-02-20 5 views
3

Я написал C DLL и некоторый код C# для тестирования, включая эту DLL и выполняющую функции из нее. Я не слишком хорошо разбираюсь в этом процессе и получаю исключение PInvokeStackImbalance, когда моя DLL-функция вызывается из исходного кода C#. Код выглядит следующим образом (я заметил самый код, чтобы выделить эту проблему):Вызов функции PInvoke несбалансированный стек при включении C 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; 
} 

Детали t Исключение составляют:

Вызов функции PInvoke 'TestConsoleGrids! TestConsoleGrids.Program :: process' имеет несбалансированный стек. Вероятно, это связано с тем, что управляемая подпись PInvoke не соответствует неуправляемой целевой сигнатуре. Убедитесь, что соглашение о вызове и параметры сигнатуры PInvoke соответствуют целевой неуправляемой подписи.

+0

Вам не нужно небезопасное ключевое слово на сигнале pinvoke. PInvoke обрабатывает сортировку с .net на родной – zebrabox

+2

Вы сделали то, что рассказали вам детали? Проверено соглашение о вызове? Проверьте документацию для класса DllImportAttribute, http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.aspx, у него есть свойство CallingConvention, попробуйте настроить его на CallingConvention.Cdecl. [DllImport (..., CallingConvention = Callingconvention.Cdecl)] –

+0

Спасибо, Лассе! Именно это и было проблемой. Я в основном следил за учебниками, и никто из них не упомянул об этом. –

ответ

5

Вызывающее соглашение неверно. Если удаление ИНТ аргументы не отключит MDA, то это Cdecl:

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

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

2

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

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

+0

Удовлетворительно фантастическое понимание, и вы должны быть правы в отношении параметров, поскольку их удаление полностью устраняет проблему. Просто объявить их как int в C#, однако, нет. –

+0

См. Обновление ..... –

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); 
+0

К сожалению, это не решит проблему. Спасибо, что направил меня на Type Marshalling, но сейчас я изучаю это. –