2014-07-31 2 views
0

У меня есть следующие (сокращенная) определение функции в моем C++ код:типа Marshalling который ссылается сама

EXPORT_API Table* OpenTableExport(); 

где таблица является структурой вида:

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; 

} 

Теперь при использовании метода, я получаю следующее исключение (в переводе с немецкого):

Поле «fNextTable» типа «Таблица» не могут быть ранжированы, никакой поддержки сортировочной не существует для этого тип.

Почему не может .NET marshall члены fNextTable и fPrevTable того же типа, которые он сортирует в любом случае?

Я также могу просто заменить ссылки в определении управляемого класса с помощью IntPtr ... но действительно ли это необходимо? (Маршаллинг тогда будет работать более или менее).

+0

Вам необходимо определить поля таблицы * как IntPtr. –

+0

Ну, хорошо, я видел эту возможность, я просто не понимаю, почему это необходимо (объект, содержащий эти поля, правильно упорядочен) – Daniel

+0

Когда вы определяете поле как таблицу, вы запрашиваете сортировку другой структуры таблицы, которая создает бесконечные рекурсии. IntPtr - это просто указатель, вы его получите, а затем переходите к другому API, ожидающему Table *, или используйте методы маршала для работы с неуправляемой памятью, например PtrToStructure. –

ответ

1

Определить структуру следующим образом:

public class Table 
{ 
    public KeyDescription fCurrKey; 
    public int fTableNo; 
    public uint fRecSize; 
    public byte fCreating; 
    public IntPtr fNextTable; 
    public IntPtr fPrevTable; 
    public FileDescription fFile; 
} 

Тест IntPtr элементы для NULL (IntPtr.Zero) и обрабатывать их. Вероятно, неуправляемый API содержит другие функции, ожидающие Table*. См. Также метод Marshal.PtrToStructure и другие низкоуровневые методы управления неуправляемым обменом памяти.

Смежные вопросы