元帅 const char **

Marshal const char **

我正在为 Arma 3 编写一个扩展。通常你可以简单地为此编写一个 C++ 库并实现这个功能

int __stdcall RVExtensionArgs(char *output, int outputSize, const char *function, const char **args, int argCnt);

我正在开发一个 C# 库,我想在其中实现这个功能。函数 RVExtensionArgs 有一个修饰名,32 位为 _RVExtensionArgs@20,64 位为 RVExtensionArgs

我正在努力处理指向 args 参数的 const char 指针的指针。我当前的实现是

#if WIN64
    [DllExport("RVExtensionArgs", CallingConvention = CallingConvention.Winapi)]
#else
    [DllExport("_RVExtensionArgs@20", CallingConvention = CallingConvention.Winapi)]
#endif
    public static int RvExtensionArgs(StringBuilder output, int outputSize,
        [MarshalAs(UnmanagedType.LPStr)] string function,
        [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4, ArraySubType = UnmanagedType.LPStr)] string[] args,
        int argCount)

使用的DllExport来自UnmanagedExports

有一些关于 here

扩展的信息

但是这样游戏就崩溃了。我很确定这是因为 args 但我无法验证它。我错过了什么吗?

我在问题的评论中回答了这个问题,但想指出将 const char** 从 C# 导出到 C++ 的最简单方法是作为 byte**.

我创建了以下 StringMarshaller class 来帮助您将 byte** 转换为 string[]。我还没有测试过 - 我可能有时间稍后再更新。

public unsafe static class StringMarshaller
{
    public static string[] Marshal(byte** nativeStrings, int stringCount)
    {
        var strings = new string[stringCount];

        for (var x = 0; x < stringCount; ++x)
        {
            if (nativeStrings[x] == null) continue;
            var length = GetStringLength(nativeStrings[x]);
            strings[x] = length == 0 
                    ? string.Empty 
                    : Encoding.UTF8.GetString(nativeStrings[x], length);
        }

        return strings;
    }

    public static int GetStringLength(byte* nativeString) 
    {
        var length = 0;

        while (*nativeString != '[=10=]')
        {
            ++length;
            ++nativeString;
        }

        return length;
    }
}