如何使用 PInvoke 将数组指针从 C# 传递到 C 库

How to pass array pointer using PInvoke from C# to C library

提问人:Iridium 提问时间:10/26/2023 最后编辑:Iridium 更新时间:10/27/2023 访问量:90

问:

我正在用 C# 编写一个软件,它需要从以 dll 形式提供的 C 库中调用一个函数。在这个库中,存在一个名为

getData(uint16_t *buffer, const uint16_t dataIndex)

使用对应于 .bufferdataIndex

在 C# 中,我尝试了以下方法来调用此函数:

[DllImport(DllPath, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
        static private extern int getData(ushort[] buffer, ushort dataIndex);

ushort[] buffer = new ushort[4096];
int response = getData(buffer, 1);

此 comiles 并运行,但缓冲区始终仅包含从 0 到 65535 的随机值。我还尝试添加到DllImport语句中,但它也没有帮助。以前,我编写了一些有效的 C++ 代码来使用此库,但不得不将代码库更改为 C#,因为我被迫使用仅存在于 C# 的库,所以我知道该库有效。[In, Out]

C++ 中的函数调用如下所示:

uint16_t Buffer[4096];
uint Respose = getFrame(Buffer, 1);

我的猜测是类型编组在某种程度上不正确,但我不知道如何正确操作。我研究了 C# 中的类型编组,但我找不到解决问题的方法。

如何使用此库获取数据?有没有另一种选择,也许使用或使用并手动读取和转换该内存地址背后的数据?如何检查传递的内存是否实际被写入?IntPtrunsafe

C# C 指针 pinvoke unsafe

评论

0赞 JonasH 10/26/2023
你的代码对我来说看起来不错,但你可能想要一个属性,参见示例。如果您已经有可用的 C++ 代码来调用它,则可以将其转换为 C++/CLI 项目。[In, Out]
0赞 shingo 10/26/2023
你能分享一个可重现的 C 代码吗?传入没有长度参数的输出缓冲区看起来不正确。
0赞 Simon Mourier 10/26/2023
您的 C 代码对传入的缓冲区到底做了什么?你可以尝试这样声明它 PS:Charset 在这里没用,不涉及 char/stringstatic private extern int getData([In, Out] ushort[] buffer, ushort dataIndex);
0赞 Iridium 10/26/2023
@JonasH我已经尝试过了,但我也没有工作。此外,我被迫使用 C# 库,因此无法进行转换。
0赞 Iridium 10/26/2023
@SimonMourier我不知道 C 代码到底是做什么的,我只是得到了一个编译的 C dll。我知道它为数据赋值,如下所示:buffer[pixelOffset + indexOfPixelInPacket] = pixel

答:

-1赞 Mark Benningfield 10/26/2023 #1

如果使用不安全的上下文(通常是与本机代码互操作的最简单方法),则可以使用指向数组第一个元素的指针,这样 GC 就不会移动它。fixed

      ushort[] buffer = new ushort[4096];
      int response = 0;
      unsafe {
        fixed (ushort *pbuff = buffer) {
          response = getData(pbuff, 1);
        }
      }
-1赞 Iridium 10/27/2023 #2

我弄清楚了问题出在哪里:我错误地使用了提供的库。由于没有文档,我联系了开发人员,我们能够解决它。数组一直被正确传输和编组,问题出在另一个函数调用上。