如何在不指定缓冲区大小的情况下将c++数组封送到c#

How to marshal C++ array to C# without specifying a buffer size?

本文关键字:c++ 情况下 数组 缓冲区      更新时间:2023-10-16

我有一个为c#方法提供数组的c++函数。我不知道会得到多少元素。我想要的只是传递一个数组(不指定元素计数)给c++函数,并让它返回填充。

My try so far:

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);

这不可能。c++代码不能神奇地知道数组的大小,也不能神奇地扩展数组以匹配数组。

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

如果不能确定数组的大小,就不能来回传递数组

如果我正确理解您的问题,您正在寻找传递数组而不提供初始化缓冲区。如果是这样的话,我非常怀疑这能否实现,因为。net中的数组是不可变的。

我目前无法访问Windows机器,但我认为你必须做这样的事情(请注意不安全关键字):

[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 condios"。

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

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