Проблема P / Invoke (несбалансированный стек) - PullRequest
2 голосов
/ 19 марта 2011

Я пытаюсь создать оболочку для нативного c ++ .dll, используя P / Invoke.

Исходный код для .dll имеет следующую указанную точку входа:

// .h-file
CHROMAPRINT_API ChromaprintContext *chromaprint_new(int algorithm);

И способ реализации:

// .cpp-file
ChromaprintContext *chromaprint_new(int algorithm)
{
    ChromaprintContextPrivate *ctx = new ChromaprintContextPrivate();
    ctx->algorithm = algorithm;
    ctx->fingerprinter = new Fingerprinter(CreateFingerprinterConfiguration(algorithm));
    return (ChromaprintContext *)ctx;
}

Тип ChromaprintContextPrivate представляет собой структуру:

>// .cpp-file
struct ChromaprintContextPrivate {
    int algorithm;
    Fingerprinter *fingerprinter;
    vector<int32_t> fingerprint;
};

Код оболочки My C #:

// .cs-file
[System.Runtime.InteropServices.DllImportAttribute(
  "libchromaprint.dll", 
  EntryPoint = "chromaprint_new")]
private static extern System.IntPtr chromaprint_new(int algorithm);

public static IntPtr Chromaprint_New(ChromaprintAlgorithm algorithm)
{
    // Hardcoded parameter for testing
    return chromaprint_new(0); // (int)algorithm
}

При вызове IntPtr ptr = Chromaprint_New(0); возникает следующее исключение MDA:
Вызов функции PInvoke 'MyProject.ChromaprintWrapper!' MyProject.ChromaprintWrapper.LibChromaPrint :: chromaprint_new 'разбалансировал стек. Это вероятно потому, что управляемая подпись PInvoke не совпадает с неуправляемой целевой подписью. Убедитесь, что соглашение о вызовах и параметры подписи PInvoke соответствуют целевой неуправляемой подписи.

Так что я понимаю, в чем проблема (количество записей в стеке не соответствует ожидаемому). Я предполагаю, что параметр метода int algorithm в порядке. Я не уверен насчет типа возврата. Должна ли это быть структура вместо указателя?

Я получил код C # выше, запустив .h-файл через P / Invoke Interop Assistant . Верный ли тип возврата? что это должно быть?

Что такое C # представление vector<int32_t> fingerprint;?
(См. ChromaprintContextPrivate структура выше.)

Ответы [ 3 ]

5 голосов
/ 19 марта 2011

Скорее всего, вам нужно указать соглашение о вызовах.

Попробуйте выполнить следующее:

[System.Runtime.InteropServices.DllImportAttribute("libchromaprint.dll", 
     EntryPoint = "chromaprint_new",
     CallingConvention=CallingConvention.Cdecl)]

По умолчанию используется Winapi (что фактически является StdCall)чтобы упростить вызов в Windows API, но это обычно не по умолчанию в большинстве библиотек C ++.

2 голосов
/ 19 марта 2011

Это из-за того, как параметры фактически передаются, соглашение о вызовах .

Попробуйте

[DllImport("libchromaprint.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr chromaprint_new(int algorithm);
0 голосов
/ 19 марта 2011

Вам необходимо объявить соглашение о вызовах cdecl для атрибута dllimport.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...