在c#中用复杂的结构包装c dll

问题描述 投票:0回答:1

我需要包装一个c dll,以便可以从c#调用它,问题是传入的结构体的属性很复杂。令人沮丧的是,child 属性只能在 c 代码内部访问,但需要在 c# 包装器中定义。

struct outer {
    .
    .
    .
    unsigned int rsi;

    unsigned int flags;

    struct internal_state *state;
};


struct internal_state {
    int (*mode)(struct outer *);

    int (**id_table)(struct outer *);

    void (*flush_output)(struct outer *);

    int id;

    int id_len;
    .
    .
    .
}

在 C 代码中,共有三个方法,本质上是 initactend,每个方法都采用 outer 结构体的实例。有问题的属性是 mode、id_table 和lush_output,如果我将它们排除在结构之外,我可以调用 init 并且它会成功返回。 Init 在外部设置状态属性,但在检查状态时没有设置任何值。

如果我尝试将 mode、id_table 和lush_output 添加为 Func/Action 类型,则调用会因以下异常而崩溃(毫不奇怪)

无法封送“internal_state”类型的字段“mode”:无法封送不可直接传送的泛型类型。

鉴于 c# 代码不触及 state 属性,有什么方法可以“控制”该属性的 c#/c 代码吗?

C# 代码示例

        public unsafe byte[] GetData(byte[] data)
        {

            var myOuter = new outer
            {
        .
        .
        .
                rsi = 128,
                flags = 8
            };

            var intitResponse = Init(ref myOuter);
            var actResponse = Act(ref myOuter, 0);
            var endResponse = End(ref myOuter);

            return dataOut;
        }

        [DllImport("lib/aec.dll", EntryPoint = "init")]
        public static extern int Init(ref outer outr);

        [DllImport("lib/aec.dll", EntryPoint = "act")]
        public static extern int Act(ref outer outr, nuint flush);

        [DllImport("lib/aec.dll", EntryPoint = "end")]
        public static extern int End(ref outer outr);

        public struct outer
        {
            .
            .
            .
            public nuint rsi;

            public nuint flags;

            public internal_state state;
        }

我尝试忽略复杂的属性,但这会导致状态属性无法在 init 方法中正确初始化,即使它从调用中返回 0。

c# c struct interop
1个回答
0
投票

state
字段是一个指针,因此如果不需要触及它,可以在结构中放置
nint
IntPtr
类型的字段。 BTW
unsigned int
应映射到
uint
而不是
nuint

public struct outer
{
    .
    .
    .
    public uint rsi;

    public uint flags;

    private nint state;
}
© www.soinside.com 2019 - 2024. All rights reserved.