【发布时间】:2014-07-31 06:36:07
【问题描述】:
我的 c++ 代码中有以下(缩短的)函数定义:
EXPORT_API Table* OpenTableExport();
其中 Table 是以下形式的结构:
typedef struct Table
{
int fCurrKey;
int fTableNo;
int fRecSize;
char fCreating;
Table* fNextTable;
Table* fPrevTable;
MyFileType fFile;
} Table;
所以,为了从托管代码中 PInvoke 这个函数,我自然地尝试了以下操作:
[DllImport("Export.dll", EntryPoint = "OpenTableExport", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public static extern Table OpenTable();
有下表类:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class Table
{
public KeyDescription fCurrKey;
public int fTableNo;
public uint fRecSize;
public byte fCreating;
public Table fNextTable;
public Table fPrevTable;
public FileDescription fFile;
}
现在使用该方法时,我得到以下异常(从德语翻译):
“Table”类型的字段“fNextTable”无法编组,该类型不存在编组支持。
为什么 .NET 在任何情况下都不能编组它编组的同一类型的 fNextTable 和 fPrevTable 成员?
我也可以用 IntPtr 替换托管类定义中的引用...但这真的有必要吗? (然后编组或多或少会起作用)。
【问题讨论】:
-
您需要将 Table* 字段定义为 IntPtr。
-
好吧,好吧,我确实看到了这种可能性,我只是不明白为什么这是必要的(包含这些字段的对象被正确编组)
-
当您将字段定义为 Table 时,您要求编组另一个 Table 结构,这会产生无休止的递归。 IntPtr 只是指针,你得到它然后传递给另一个期望 Table* 的 API,或者使用 Marshal 方法来处理非托管内存,比如 PtrToStructure。
-
啊,好吧,我明白你的意思了,在某种程度上是有道理的(尽管递归不一定是无止境的,我想这取决于编组的实现方式)。我将其放入答案中,我很乐意接受,非常感谢。
标签: c# c pinvoke marshalling