Marshal const char **

时间:2017-02-24 16:06:38

标签: c# marshalling

我正在为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但我无法验证它。我错过了什么吗?

1 个答案:

答案 0 :(得分:1)

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

我创建了下面的StringMarshaller类来帮助你将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 != '\0')
        {
            ++length;
            ++nativeString;
        }

        return length;
    }
}