我正在尝试使用 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 的 C# 表示是什么?指纹;
?
(请参阅上面的 ChromaprintContextPrivate
结构。)
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. This 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.)
发布评论
评论(3)
您很可能需要指定调用约定。
尝试以下操作:
默认情况下,这使用 Winapi (实际上是 StdCall),以便更轻松地调用 Windows API,但这通常不是大多数 C++ 库的默认设置。
You most likely need to specify the calling convention.
Try the following:
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 属性上声明 cdecl 调用约定。
You need to declare cdecl calling convention on the dllimport attribute.