【问题标题】:Unmanaged code call, array parsing非托管代码调用、数组解析
【发布时间】:2017-07-09 19:01:11
【问题描述】:

我正在开发 Arma 3 游戏,您可以在其中编写自己的扩展(即 C++ 或 C# 库)。这些扩展有一个定义的入口点,即这个 DLL 接口

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

在 C# 中实现这一点时,RVExtension 的入口点将是

[DllExport("_RVExtension@12", CallingConvention = CallingConvention.Winapi)]
public static void RvExtension(StringBuilder output, int outputSize,
    [MarshalAs(UnmanagedType.LPStr)] string function)
{
    output.Append("Foo");
}

我正在为 DLLExport 使用 this 库。

由于RVExtensionArgs 的入口点很新,我也想实现它。到目前为止,我的解决方案是这个:

[DllExport("_RVExtensionArgs@20", CallingConvention = CallingConvention.Winapi)]
public static int RvExtensionArgs(StringBuilder output, int outputSize,
    [MarshalAs(UnmanagedType.LPStr)] string function, [MarshalAs(UnmanagedType.LPArray)] string[] args,
        int argCount)
{
    output.Append("Foo");
}

一般来说这是可行的,但是为 args 参数传递的数组未正确转换。你只会得到传递数组的第一个元素。

我尝试定义 LPArray SizeConst 属性,但这必须是我无法提供的固定大小。传递的数组元素最多可达 1024 个。另外,我在使用测试控制台访问 DLL 时遇到了 MarshalException。

如何解决此问题?

【问题讨论】:

  • 不是 SizeConst,请改用 SizeParamIndex。
  • 好吧,这太容易了。为了完整起见,您会将其发布为答案吗?

标签: c# arrays unmanaged


【解决方案1】:

为了完整起见,这里是 Hans Passant 提出的解决方案。

public static int RvExtensionArgs(StringBuilder output, int outputSize,
        [MarshalAs(UnmanagedType.LPStr)] string function,
        [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr, SizeParamIndex = 4)] string[] args,
        int argCount)
{
    output.Append("Foo");
}

【讨论】:

    猜你喜欢
    • 2013-08-24
    • 2010-09-18
    • 1970-01-01
    • 2015-02-24
    • 1970-01-01
    • 1970-01-01
    • 2011-01-31
    • 2013-12-29
    • 1970-01-01
    相关资源
    最近更新 更多