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
내부의 구조체를 IntPtr
으로 참조해야합니다. 비트 필드의 값에 쉽게 액세스 할 수 있도록하는 속성을 추가했습니다.
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을 호출합니다. 이 시점에서 라이브러리는 두 개의 서로 다른 크기로 초기화되었다는 경고를 받으면서 불안정하게 만듭니다 (특정 작업 후 AccessViolationException
초 발생).
추가 된 속성이 구조체의 크기에 포함되며 관리되지 않는 버전보다 커야합니까? 나는 그들을 제거하고 어떤 일이 일어나는지 보 겠지만, 내 코드는 그것들에 크게 의존하기 때문에 그것을 어렵게 만든다.
Size
속성과 함께 StructLayoutAttribute
을 사용해야합니까? 그것에 대해 나를 혼란스럽게하는 유일한 것은 IntPtr
입니다. 라이브러리는 엄격하게 32 비트이므로 계속해서 안전하게 해당 필드가 32 비트라고 가정 할 수 있습니까?
아, 알겠습니다. 나는 실종 된'*'을 알아 차리지 못했다. 이 솔루션의 문제점은'Agraphinfo_t' 구조체가 (필드의 수면에서) MASSIVE이고 라이브러리가 컴파일 된 방법에 따라 다른 필드를 사용한다는 것입니다. 어떤 컴파일러 플래그를 사용했는지 알지 못하기 때문에 포함 할 필드가 확실하지 않습니다. 어떤 팁? –
불행히도 아닙니다. 크기를 맞추려면, 관리되지 않는'Agraphinfo_t' 구조체와 같은 크기의 크기 (구조체 내)를 차지하는 슬롯에 * something *을 제공해야합니다. 바이트 배열을 사용하여 참조가 아닌 인라인 공간으로 취급되도록 적절한 마샬링 플래그를 사용할 수도 있지만 크기를 계산해야합니다. sizeof (Agraphinfo_t)를 인쇄하는 작은 C 프로그램. 그래도 약속은 안돼 - 미안해! – itowlson
그게 가능합니다. 그 동안, 나는 aginitlib에 대한 자체 호출을하는 라이브러리 부분이 다른 것들보다 먼저 호출되어야하고 관리되는 래퍼에서 수동으로 호출하는 기능을 제거해야한다는 요구 사항을 추가했다. 작동하지만 꼭 지키고 싶은 것은 아닙니다. –