【问题标题】:.NET Core on Linux - Marshal structuresLinux 上的 .NET Core - 元帅结构
【发布时间】:2019-12-20 18:59:45
【问题描述】:

我有一个 .NET Core 控制台应用程序,它调用 C++ 库中的一些函数。我试图调用 simpty 的函数在一些 settings 中获取,并将结果输出到 result

C++:

struct settings
{
    char* input_path;
    char* first_file;
    char* second_file;
    char* mask;
    char* log_path;
    int count_accepted;
    double confidence;
    char* device;
};

struct result
{
    int count;
    foo* foos;
    bool is_preprocessed;
    double duration;
};

bool process_input(const settings& settings, result* result);

C#:

[StructLayout(LayoutKind.Sequential)]
public struct Settings
{
    [MarshalAs(UnmanagedType.LPStr)]
    public string input_path;
    [MarshalAs(UnmanagedType.LPStr)]
    public string first_file;
    [MarshalAs(UnmanagedType.LPStr)]
    public string second_file;
    [MarshalAs(UnmanagedType.LPStr)]
    public string mask;
    [MarshalAs(UnmanagedType.LPStr)]
    public string log_path;
    [MarshalAs(UnmanagedType.I4)]
    public int count_accepted;
    [MarshalAs(UnmanagedType.R8)]
    public double confidence;
    [MarshalAs(UnmanagedType.LPStr)]
    public string device;
}

[StructLayout(LayoutKind.Sequential)]
public struct Result
{
    [MarshalAs(UnmanagedType.I4)]
    public int count;
    [MarshalAs(UnmanagedType.SysInt)]
    public IntPtr foos;
    [MarshalAs(UnmanagedType.I1)]
    public bool is_preprocessed;
    [MarshalAs(UnmanagedType.R8)]
    public double duration;
}

[DllImport("myLib", EntryPoint = "process_input", CallingConvention = CallingConvention.Cdecl)]
[return:MarshalAs(UnmanagedType.I1)]
public static extern bool ProcessInput(Settings settings, out Result result);

这一切都适用于 Windows,但不适用于 Linux。当我在 C++ 端(来自process_input)打印设置时,我在 int 和 double 属性中得到完全不同的值,并且在尝试访问 char* 属性时出现分段错误。

我还尝试从 C++ 代码(Windows 和 Linux)调用这个库,它按预期工作。据我了解,这是一个编组问题,但我自己无法确定。我是一名 C# 开发人员,对 C++ 或 PInvoke 或 Linux 没有太多经验。

我使用 Windows 10 (x64) 和 Ubuntu 16.04 (x64)。

【问题讨论】:

  • 从一些调试代码开始。检查 C# 和 C++ 中结构的偏移量。它们匹配吗?
  • 是的,偏移量匹配。
  • 现在检查数据是否正确传输
  • 我该怎么做?
  • 在 WIndows 上,我原以为 C# 会在堆栈上按值传递结构。但也许调用约定不像我预期的那样。您是否在 Windows 上运行 64 位进程?在任何情况下,您的 C# 代码由值隐含,而 C++ 代码由 ref 隐含。所以这是一个不匹配。您应该将 C# 更改为通过 ref 显式传递。

标签: c++ linux .net-core pinvoke marshalling


【解决方案1】:

作为 cmets 中的 David Heffernan suggested,我添加了一个明确的 ref 关键字并且它起作用了。

这是我之前的函数签名:

public static extern bool ProcessInput(Settings settings, out Result result);

之后:

public static extern bool ProcessInput(ref Settings settings, out Result result);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-04
    相关资源
    最近更新 更多