Создание C ++ DLL для C # - PullRequest
3 голосов
/ 05 октября 2011

Я сделал очень простой Dll вроде этого:

extern "C"
{
  __declspec(dllexport) int Try(int v)
  {
    return 10 + v;
  }
}

Затем я хочу использовать его в моем приложении на C #:

class Program
{
    [DllImport("TestLib.dll")]
    public static extern int Try(int v);

    static void Main(string[] args)
    {
        Console.WriteLine("Wynik: " + Try(20));
        Console.ReadLine();
    }
}

Это работало, пока я не попыталсяпа параметр.Теперь у меня появляется следующая ошибка во время выполнения:

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

Я понятия не имею, в чем проблема.

Ответы [ 2 ]

5 голосов
/ 05 октября 2011

Полученное вами сообщение об ошибке содержит полезный совет:

Убедитесь, что соглашение о вызовах и параметры подписи PInvoke соответствуют целевой неуправляемой подписи.

У вас должно быть одинаковое соглашение о вызовах, указанное на обеих сторонах (сборка C ++ dll и C #).В C ++ вы можете указать это, добавив объявление функции с одним из __cdecl, __stdcall и т. Д.


extern "C"
{
  __declspec(dllexport) int <strong>__stdcall</strong> Try(int v)
  {
    return 10 + v;
  }
}

На стороне C # вы указываете его с атрибутом DllImport, по умолчанию используется CallingConvention.StdCall, который соответствует __stdcallв C ++, похоже, у вас есть __cdecl на стороне C ++.Чтобы решить эту проблему, используйте __stdcall в вашей DLL, как показано выше, или используйте CDecl в C # следующим образом:


class Program
{
    [DllImport("TestLib.dll", <strong>CallingConvention=CallingConvention.Cdecl</strong>)]
    public static extern int Try(int v);

    static void Main(string[] args)
    {
        Console.WriteLine("Wynik: " + Try(20));
        Console.ReadLine();
    }
}

2 голосов
/ 05 октября 2011

Соглашение о вызовах по умолчанию в C и C ++: __cdecl; соглашение о вызовах по умолчанию, используемое .NET P / Invoke, равно __stdcall - вам нужно согласовать эти два.

  • Либо сделайте свою нативную функцию __stdcall, как предложил Ганс:

    __declspec(dllexport) int __stdcall Try(int v)
    
  • Или используйте свою управляемую подпись P / Invoke, используя __cdecl:

    [DllImport("TestLib.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern int Try(int v);
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...