P / Invoke问题(不平衡堆栈)

时间:2011-03-19 01:44:08

标签: c# c++ pinvoke

我正在尝试使用P / Invoke为本机c ++ .dll创建一个包装器。

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

我的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没问题。我不确定返回类型。它应该是结构而不是指针吗?

我通过P/Invoke Interop Assistant运行.h文件获得了上面的C#代码。返回类型错了吗?它应该是什么?

vector<int32_t> fingerprint;的C#表示是什么?
(参见上面的ChromaprintContextPrivate结构。)

3 个答案:

答案 0 :(得分:5)

您很可能需要指定调用约定。

尝试以下方法:

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

默认情况下,它使用Winapi(实际上是StdCall)来更容易调用Windows API,但这通常不是大多数C ++库的默认设置。

答案 1 :(得分:2)

这是因为参数实际传递的方式是调用约定

尝试

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

答案 2 :(得分:0)

您需要在dllimport属性上声明cdecl调用约定。