C# P/Invoke:如何实现结构化参数字段的双重间接寻址

发布于 2024-07-22 15:36:52 字数 774 浏览 2 评论 0原文

我正在从 C# 调用本机 dll。 对于所讨论的特定函数,我需要的参数之一是一个包含双重间接字段(指向指针的指针)的结构。

例如,采用以下 C 原型和结构:

int someFunc(SomeStruct* result);

struct SomeStruct
{
     DWORD foo;
     AnotherStruct** ppResultStruct;
}

struct AnotherStruct
{
     DWORD bar;
}

以下 C# 代码仅为字段 AnotherStruct 提供单级间接,这是不正确的:

[DllImport("my.dll")]
public static extern int someFunc(SomeClass result);

[StructLayout(LayoutKind.Sequential)
public class SomeClass
{
    int foo;
    AnotherClass resultClass;
}

[StructLayout(LayoutKind.Sequential)]
public class AnotherClass
{
    int bar;
}

如何实现此处所需的双重间接? 我知道如何在函数的双重间接参数的情况下执行此操作,但我对它嵌入在结构中的事实感到困惑。

也许我应该将 AnotherClass 字段声明为 IntPtr,然后使用不安全的代码为其分配适当的值。 这是一种有效的方法吗?还有其他/更好的选择吗?

I am calling into a native dll from C#. For the specific function in question, one of the parameters I need is a structure which contains a doubly-indirect field (pointer to a pointer).

For example, take the following C prototype and structs:

int someFunc(SomeStruct* result);

struct SomeStruct
{
     DWORD foo;
     AnotherStruct** ppResultStruct;
}

struct AnotherStruct
{
     DWORD bar;
}

The following C# code provides only a single level of indirection for the field AnotherStruct, which is incorrect:

[DllImport("my.dll")]
public static extern int someFunc(SomeClass result);

[StructLayout(LayoutKind.Sequential)
public class SomeClass
{
    int foo;
    AnotherClass resultClass;
}

[StructLayout(LayoutKind.Sequential)]
public class AnotherClass
{
    int bar;
}

How can I achieve the double-indirection that's required here? I know how to do it in the case of a doubly-indirect parameter to a function, but I'm confused by the fact that it's embedded in a struct.

Maybe I should declare the AnotherClass field as an IntPtr, and then resort to unsafe code to assign it an appropriate value. Is that a valid approach, and are there any other/better options?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

清引 2024-07-29 15:36:52

如果没有自定义 marashaler,您就无法构建既包含标准内联结构定义又包含双重间接寻址的类。 这种类型的编组需要一些魔法才能实现。

解决这个问题的最佳方法是将双重间接寻址视为实际的指针。 然后用漂亮的财产来驱除邪恶

[StructLayout(LayoutKind.Sequential)
public class SomeClass
{
    int foo;
    IntPtr resultPtr;
    AnotherStruct resultStruct { 
      get { 
        var temp = (IntPtr)Marshal.PtrToStructure(resultPtr, typeof(IntPtr));
        return (AnotherStruct)Marshal.PtrToStructure(temp, typeof(AnotherStruct));
      }
    }

}

[StructLayout(LayoutKind.Sequential)]
public class AnotherStruct
{
    int bar;
}

Without a custom marashaler you cannot build a class that both contains a standard inline struct definition and double indirection. This type of marshaling requires a bit of magic to achieve.

The best way to approach this is to treat the double indirection as a pointer which it actual is. Then use a pretty property to take care of the evilness

[StructLayout(LayoutKind.Sequential)
public class SomeClass
{
    int foo;
    IntPtr resultPtr;
    AnotherStruct resultStruct { 
      get { 
        var temp = (IntPtr)Marshal.PtrToStructure(resultPtr, typeof(IntPtr));
        return (AnotherStruct)Marshal.PtrToStructure(temp, typeof(AnotherStruct));
      }
    }

}

[StructLayout(LayoutKind.Sequential)]
public class AnotherStruct
{
    int bar;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文