我需要包装一个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 代码中,共有三个方法,本质上是 init、act、end,每个方法都采用 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。
state
字段是一个指针,因此如果不需要触及它,可以在结构中放置nint
或IntPtr
类型的字段。 BTW unsigned int
应映射到 uint
而不是 nuint
。
public struct outer
{
.
.
.
public uint rsi;
public uint flags;
private nint state;
}