【问题标题】:How to marshal C++ array to C# without specifying a buffer size?如何在不指定缓冲区大小的情况下将 C++ 数组编组为 C#?
【发布时间】:2015-07-10 13:44:24
【问题描述】:

我有一个为 C# 方法提供数组的 C++ 函数。我不知道我会得到多少元素作为回报。我想要的只是将一个数组(不指定元素计数)传递给 C++ 函数并重新填充。

到目前为止我的尝试:

C++ 代码

unsigned int lib_infos(
    const char *code,
    char **err,
    int err_len,
    char **linkinfo,
    unsigned int* linksCount);

C#代码

[DllImport("mylib.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern uint lib_infos(
    [MarshalAs(UnmanagedType.LPStr)] string code,
    [MarshalAs(UnmanagedType.LPStr)] StringBuilder err,
    int err_len,
    [MarshalAs(UnmanagedType.LPArray,SizeParamIndex=1)] string[] linkInfo,
    out uint linksCount);

【问题讨论】:

  • 我知道这有点离题,但是您可以使用 google 协议缓冲区在 c# 和 c++ 之间传递数据结构,并在两侧进行编译类型检查和 OO 访问。

标签: c# c++ arrays marshalling


【解决方案1】:

这是不可能的。 C++ 代码不能神奇地知道数组的大小,或者神奇地扩展你的数组以匹配。

必须有一个数组大小的通信协议——要么你告诉它数组的大小并请求 N 个元素,有效地,要么它告诉你有 N 个元素,然后你提供一个该大小的数组。

如果无法确定数组的大小,则不能来回传递数组。

【讨论】:

  • 听起来很合理。如果我知道项目计数,你能举个适当的例子吗?
【解决方案2】:

如果我正确理解了您的问题,您希望在不提供初始化缓冲区的情况下传递数组。如果是这样,我非常怀疑这是否可以实现,因为 .NET 中的数组是不可变的。

我目前无法访问 Windows 机器,但我认为您必须这样做(请注意 unsafe 关键字):

[DllImport("mylib.dll", CallingConvention = CallingConvention.Cdecl)]
private unsafe static extern uint lib_infos(
    byte * code,
    [MarshalAs(UnmanagedType.LPStr)] StringBuilder err,
    int err_len,
    [MarshalAs(UnmanagedType.LPArray,SizeParamIndex=1)] string[] linkInfo,
    out uint linksCount);

当然,除非您在编译时添加 /unsafe(或类似的)标志,否则这不会编译。

如果我是对的,我只需要对你说:“ve con dios”。

话虽如此,您仍然需要在非托管层中分配内存,然后——为了最终用户——包装 P/Invoke 调用以创建一个实际的 string 以返回。

【讨论】:

  • 我想你想说“vaya con Dios”。总之,不错的尝试。和很好的答案。看起来OP想要制作某种包装器。对我也有用。
【解决方案3】:

在末尾添加一个标记值。然后读取值直到哨兵值,然后创建适当大小的 c# 数组。

【讨论】:

    猜你喜欢
    • 2021-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-22
    • 2016-10-13
    • 2013-06-14
    • 1970-01-01
    • 2018-10-09
    相关资源
    最近更新 更多