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

发布于 2024-10-22 20:22:41 字数 1774 浏览 2 评论 0 原文

我正在尝试使用 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.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

撩心不撩汉 2024-10-29 20:22:41

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

尝试以下操作:

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

默认情况下,这使用 Winapi (实际上是 StdCall),以便更轻松地调用 Windows API,但这通常不是大多数 C++ 库的默认设置。

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.

心是晴朗的。 2024-10-29 20:22:41

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

尝试

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

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);
一笔一画续写前缘 2024-10-29 20:22:41

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文