我正在尝试使用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
结构。)
答案 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调用约定。