2011-03-19 12 views
2

P/Invokeを使用してネイティブのC++ .dllのラッパーを作成しようとしています。P/Invoke problem(アンバランススタック)

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

そしてメソッドの実装:

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

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

ChromaprintContextPrivate型構造である

の.dllのソースコードは、指定された次のエントリ・ポイントを有しています

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 
}

には、次のMDAの例外が発生します:
のPInvoke 関数 'MyProject.ChromaprintWrapper!' MyProject.ChromaprintWrapper.LibChromaPrint :: chromaprint_new」へのコールスタックをアンバランスがあります。これは、管理対象のPInvokeシグネチャがアンマネージ対象シグネチャと一致しないためです。 PInvokeシグネチャの呼び出し規約とパラメータが、対象となる管理されていないシグネチャと一致することを確認します。

私は問題が何であるか理解しています(スタック上のエントリの数は予想されないものです)。私はメソッドのパラメータint algorithmがOKであると仮定しています。私はしかし、戻り値の型についてはよく分かりません。ポインタの代わりに構造体でなければなりませんか?

上記のC#コードは、.h-ファイルをP/Invoke Interop Assistantまで実行して取得しました。戻り値の型は間違っていますか?それは何でしょうか?

vector<int32_t> fingerprint;のC#表現は何ですか?
(上記ChromaprintContextPrivate構造を参照してください。)

答えて

5

を試してみてください。

は、次の試してみてください。デフォルトでは

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

が、これは、Windows APIを呼び出すやすくするために(効果的にSTDCALLである)Winapiを使用していますが、これは通常、ほとんどのC++ライブラリのデフォルトではありません。

2

をそれが原因のパラメータは、実際に、呼び出し規約を渡す方法のためです。

は、あなたが最も可能性の高い呼び出し規約を指定する必要が

[DllImport("libchromaprint.dll", CallingConvention = CallingConvention.Cdecl)] 
private static extern IntPtr chromaprint_new(int algorithm); 
0

dllimport属性でcdecl呼び出し規約を宣言する必要があります。