开发者

P/Invoke problem (unbalanced stack)

I am trying to make a wrapper for a native c++ .dll using P/Invoke.

The source code for the .dll has the following entry point specified:

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

And the method implementation:

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

The ChromaprintContextPrivate type is a structure:

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

My C# wrapper code:

// .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
}

Calling IntPtr ptr = Chromaprint_New(0); raises the following MDA exception:

A call to PInvoke function 'MyProject.ChromaprintWrapper!'MyProject.ChromaprintWrapper.LibChromaPrint::chromaprint_new' has unbalanced the stack. T开发者_Python百科his is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.

So I understand what the problem is (the number of entries on the stack isn't what is expected). I'm assuming the method parameter int algorithm is ok. I'm not sure about the return type though. Should it be a structure instead of a pointer?

I got the C# code above by running the .h-file through P/Invoke Interop Assistant. Is the return type wrong? what should it be?

What is the C# representation of vector<int32_t> fingerprint;?

(See ChromaprintContextPrivate structure above.)


You most likely need to specify the calling convention.

Try the following:

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

By default, this uses Winapi (which is effectively StdCall) to make it easier to call into the Windows API, but this is not typically the default on most C++ libraries.


It's because of how the parameters are actually passed, the calling convention.

Try

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


You need to declare cdecl calling convention on the dllimport attribute.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜