【发布时间】:2010-01-09 00:56:57
【问题描述】:
我正在通过 P/Invoke 使用非托管库,它使用三个结构(尽管它们都有相同的基本布局,所以我只发布一个):
struct Agraph_t {
int tag:4;
int kind:4;
int handle:24;
char **attr;
char *didset;
char *name;
Agdata_t *univ;
Dict_t *nodes, *inedges, *outedges;
Agraph_t *root;
Agnode_t *meta_node;
Agproto_t *proto;
Agraphinfo_t u;
};
由于我的包装器使用这些对象的方式,我必须将Agraph_t 中的结构称为IntPtrs。我添加了一些属性,使访问位域的值更容易。
public struct Agraph_t {
public uint tag_kind_handle;
public IntPtr attr;
public string didset;
public string name;
public IntPtr univ;
public IntPtr nodes, inedges, outedges;
public IntPtr root;
public IntPtr meta_node;
public IntPtr proto;
public IntPtr u;
public uint Tag {
get { return (tag_kind_handle & 15u); }
}
public uint Kind {
get { return (tag_kind_handle & 240u) / 16; }
}
public uint Handle {
get { return (tag_kind_handle & 4294967040u) / 256; }
}
}
在做任何事情之前,我必须通过给它三个结构中每个结构的大小来初始化非托管库。
aginitlib(Marshal.SizeOf(typeof(Agraph_t)), ..., ...);
这样做时我没有收到错误,我可以很好地使用该库。但是,库的一部分使用非托管结构的大小自己调用 aginitlib(我无法控制)。那时,库警告我它已经用两种不同的大小进行了初始化,这使得它变得不稳定(在某些操作后抛出 AccessViolationExceptions)。
添加的属性是否已计入结构的大小并使其大于非托管版本?我会删除它们,看看会发生什么,但我的代码在很大程度上依赖于它们,这很困难。
我是否需要将StructLayoutAttribute 与Size 属性一起使用?唯一让我感到困惑的是IntPtrs。该库是严格 32 位的,所以我可以继续假设这些字段始终是 32 位吗?
【问题讨论】:
标签: c# .net struct pinvoke marshalling