MarshalAs 嵌套结构

2024-03-13

我有两个 C++ 结构,在从 C# 调用 DLL 方法时必须将它们作为参数发送。

例如,让我们将它们定义为:

struct A
{
    int data;
}

struct B
{
    int MoreData;
    A * SomeData;
}

我需要从 C# 调用的方法具有以下签名:

int operation (B * data);

(请注意,我无法控制这些 C++ 结构或方法。)

在 C# 中,我将这些结构定义为类:

[StructLayout(LayoutKind.Sequential)]
class A
{
    public int data;
}

[StructLayout(LayoutKind.Sequential)]
class B
{
    public int MoreData;

    [MarshalAs(UnmanagedType.Struct)]
    public A SomeData;
}

我创建了一个“调试 dll”以从 C# 调用,以确保在 C++ 方法中正确接收所有数据。到目前为止,只有嵌套结构指针之前的数据被正确发送。

当我尝试从嵌套结构 (B->A->data) 读取数据时,出现读取冲突错误 (AccessViolationException)。

如何封送嵌套结构以便能够在 C++ 方法中读取它?


您的 C# 声明并不等效,它会内联生成 SomeData 字段。换句话说,等效的本机声明将是:

struct B
{
    int MoreData;
    A SomeData;
}

P/Invoke 编组器无法处理作为指针的成员。这是一个内存管理问题,谁拥有该指针并负责删除它是非常模糊的。为了使这项工作正常进行,您必须像这样声明结构:

    struct B {
        public int MoreData;
        public IntPtr SomeData;
    }

并亲自编组它。像这样:

        var b = new B();
        b.MoreData = 0x12345678;
        var a = new A();
        a.Data = 0x789abcde;
        int len = Marshal.SizeOf(a);
        b.SomeData = Marshal.AllocCoTaskMem(len);
        try {
            Marshal.StructureToPtr(a, b.SomeData, false);
            someFunction(ref b);
        }
        finally {
            Marshal.FreeCoTaskMem(b.SomeData);
        }

此代码隐含的是该指针由托管代码拥有,并且它释放内存(FreeCoTaskMem 调用)。如果本机代码复制传递的结构,那么这将是一个问题,当它尝试取消引用指针时,它将读取错误数据或炸弹。Not释放内存也不是一个选项,这会产生不可插入的内存泄漏。因为本机代码无法使用free()函数来释放它。如果您最终陷入了这个雷区,那么您将必须用 C++/CLI 语言编写一个包装器,以便您可以使用 CRT 的 malloc() 函数。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MarshalAs 嵌套结构 的相关文章

随机推荐

  • 在 Emacs 启动期间运行我自己的代码

    假设我有自己的 elisp 代码 bin hello el The emacs文件有以下代码要运行hello el在启动时 add to list load path bin elisp require hello 但是 我收到以下错误消息
  • 如何修复“重大更改:webpack < 5 默认情况下用于包含 Node.js 核心模块的 polyfills”错误?

    我想用 web3 and walletconnect web3 provider vue 和 laravel 8 上的包 我通过 npm i save web3 walletconnect web3 provider 命令安装它 然后添加以
  • SELECT 在 ON 子句中包含子字符串?

    我在ABAP中有以下选择语句 SELECT munic mandt VREFER BIS AB ZZELECDATE ZZCERTDATE CONSYEAR ZDIMO ZZONE M ZZONE T USAGE M USAGE T M2M
  • 注释空行[重复]

    这个问题在这里已经有答案了 在 vs code 中注释多行时使用ctrl 有没有办法也注释选择中的空白行 例如 如果我有以下代码 def A line1 line2 当所有这些行都被选择并注释时ctrl 我也希望空白行得到注释 例如 def
  • Chrome 扩展程序身份:OAuth2 请求失败:服务响应错误:“错误请求”

    我跟着https developer chrome com extensions tut oauth https developer chrome com extensions tut oauth完全一步一步 但我被困在 https dev
  • 如何使用 ASP.Net MVC 制作向导

    我们的网站有多个 向导 在多个页面上收集各种数据 并且直到最后一步才能将其提交到数据库 使用 ASP Net MVC 制作这样的向导的最佳 正确方法是什么 编辑 我的老板现在说 没有 javascript 关于如何绕过该限制有什么想法吗 我
  • 在 D 中制作结构体的堆副本

    如何创建堆栈上结构的垃圾收集副本 来自 C 背景 我的第一个猜测是像下面这样的复制构造函数 但它对于 D 来说似乎不太惯用 而且我在我看过的任何 D 项目中都没有看到过这样的复制构造函数 struct Foo immutable int b
  • 如何从控制器类打开 JavaFX FileChooser?

    我的问题是所有使用的例子FileChooser要求你通过一个阶段 唯一的问题是我的 UI 是在fxml文件 它使用与主阶段分开的控制器类 FXML protected void locateFile ActionEvent event Fi
  • 在 R 中,增长列表与增长向量一样低效吗?

    some list lt list for i in 1 1000 some list i lt i 我想知道如果 some list 是一个向量 这是否同样低效 答案似乎是 是 您可以对其进行基准测试 f function some li
  • 列表框.SelectedItem

    我有一个ListBox与填充的物品TextBoxes 从列表中进行选择时如何识别所选的文本字符串ListBox 这是我的 XAML 代码ListBox
  • CSS 内嵌边框

    我需要创建一个纯色插入边框 这是我正在使用的 CSS 代码 border 10px inset rgba 51 153 0 0 65 不幸的是 这会创建 3D 脊状边框 忽略正方形和黑色描述框 你可以使用box shadow 可能 some
  • 如何从 SvelteKit 应用程序发送安全的 API 请求,而不在客户端显示 API 密钥?

    我正在将 Supabase 用于新的 Sveltekit 应用程序 这个模板 https github com joshnuss svelte supabase 目前 我正在客户端传递 Supabase 密钥 如下所示 const supa
  • 相当于 C++ 中 Rust 的特定模板用法

    Rust 中是否有一个功能可以使这样的事情成为可能 据我所知 Rust 的泛型函 数不可能做到这一点 因为它们仅适用于数据类型 而不适用于值 include
  • 在asp.net core 3.1中使用log4net和Microknights登录数据库不起作用

    我看过很多文章说 net core 不支持 AdoNetAppender 但我们可以使用 MicroKnights 来做同样的事情 我正在尝试使用相同的方法在 net core 3 1 应用程序中实现数据库日志记录 但仍然没有成功 我放置在
  • 网页抓取中如何获取重定向的URL?

    我想要的只是请求实际 url 后重定向的 url 这是实际的网址https metric picodi net us r 19761 当我使用此 url 在浏览器上按 Enter 键时 它会将我重定向到这样的 url https www o
  • 仅将天数和时间(小时 x 分钟 x 秒)转换为时间

    我有一个数据框 在其中比较两个不同日期之间的差异以获得小时和分钟的差异 例如 start date 2018 07 03 16 03 00 data final 2018 07 05 00 00 00 duration data final
  • 交叉联接行为 (SQLServer 2008)

    我一直在尝试找出我的查询的问题 该查询实际上是由 hibernate 从 HQL 生成的 但生成的 SQL 并没有达到我的预期 稍微修改 SQL 会产生正确的结果 但我不确定为什么修改会产生任何差异 原始查询 不返回任何行 select s
  • 如何在 Rust 中惯用地替换特定字符?

    所以我有字符串 Hello World 并想替换 和 这样新字符串就是 Hello World 在 Ruby 中 我们可以使用以下命令轻松完成此操作gsub method Hello World gsub 如何在 Rust 中惯用地做到这一
  • 创建随机二进制文件

    我正在尝试使用 python 创建一个随机二进制文件 这就是我已经得到的 f open filename wb for i in xrange size kb for ii in xrange 1024 4 f write struct p
  • MarshalAs 嵌套结构

    我有两个 C 结构 在从 C 调用 DLL 方法时必须将它们作为参数发送 例如 让我们将它们定义为 struct A int data struct B int MoreData A SomeData 我需要从 C 调用的方法具有以下签名