Простой тест взаимодействия;Стек не сбалансирован простым звонком - PullRequest
1 голос
/ 21 февраля 2011

В настоящее время я изучаю проблему, связанную с взаимодействием, и написал небольшую тестовую программу, чтобы помочь мне понять, что происходит (рассматриваемая проблема связана с вызовом более сложной нативной функции, и ее было бы сложно опубликоватьздесь).

В любом случае, у меня есть очень простая нативная dll, которая включает в себя только следующий код:

extern "C" __declspec(dllexport) void Foo( int* arr, int size );

void Foo( int* arr, int size )
{
    for( int i = 0; i < size; ++i )
    {
        *arr++ = i;
    }
}

Я вызываю эту функцию из C # примерно так:

[DllImport("Interop.dll")]
public static extern void Foo( int[] arr, int size );

static void Main(...)
{
    Test();
}

private static void Test()
{
    int[] arr = new int[100];
    Foo( arr, arr.Length );
}

После выполнения «Тест» я получаю следующую ошибку:

Обнаружен PInvokeStackImblanace

Вызов функции PInvoke 'WindowsFormsApplication2! WindowsFormsApplication2.Form1:: Foo 'разбалансировал стек.Это вероятно потому, что управляемая подпись PInvoke не совпадает с неуправляемой целевой подписью.Убедитесь, что соглашение о вызовах и параметры подписи PInvoke соответствуют целевой неуправляемой подписи.

Итак, я не эксперт по взаимодействию, но не вижу проблемы с этим кодом.Собственная подпись ожидает указатель на int, я передаю ссылку на int[].Тем не менее, это не работает, поэтому я должен быть неправ в чем-то.Заранее спасибо.

РЕДАКТИРОВАТЬ: ОК, я перешел на тест, чтобы быть максимально простым:

extern "C" __declspec(dllexport) void Foo( int i );

void Foo( int i ) { }

C #:

[DllImport("Interop.dll")]
public static extern void Foo( int i  );

private void Test()
{
    Foo( 1 );
}

Результаты те жеошибка.Я пропустил какой-то цельный урок по соглашениям о вызовах, используемых во взаимодействии?Что здесь происходит?

1 Ответ

4 голосов
/ 22 февраля 2011

Вам необходимо указать правильное соглашение о вызовах .Соглашение о вызовах по умолчанию для программ на C / C ++: cdecl , но соглашение о вызовах по умолчанию при импорте через PInvoke: StdCall .Поэтому вам нужно указать соглашение Cdecl при импорте или __stdcall при экспорте.Например:

[DllImport("Interop.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void Foo( int i  );

private void Test()
{
    Foo( 1 );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...