Estruturas aninhadas em C# P/Invoke
Pergunta
Estou tentando chamar uma DLL não gerenciada que tem a seguinte estrutura:
typedef struct
{
int num_objects;
ppr_object_type *objects;
} ppr_object_list_type;
ppr_coordinate_type;
typedef struct
{
int model_id;
ppr_coordinate_type position;
float scale_factor;
float size;
ppr_rotation_type rotation;
int nominal_width;
int nominal_height;
float confidence;
int num_landmarks;
ppr_landmark_type *landmarks;
} ppr_object_type;
typedef struct
{
float x;
float y;
}
typedef struct
{
float yaw;
float pitch;
float roll;
ppr_precision_type precision;
} ppr_rotation_type;
É isso que estou usando no lado C#:
[StructLayout(LayoutKind.Sequential)]
public struct ObjectInfo
{
public int numObjects;
public ObjectType objListPointer;
}
[StructLayout(LayoutKind.Sequential)]
public struct ObjectType
{
int model_id;
Coordinate position;
float scale_factor;
float size;
Rotation rotation;
int nominal_width;
int nominal_height;
float confidence;
int num_landmarks;
IntPtr landmarks;
}
[StructLayout(LayoutKind.Sequential)]
public struct Coordinate
{
float x;
float y;
}
[StructLayout(LayoutKind.Sequential)]
public struct Rotation
{
float yaw;
float pitch;
float roll;
int precision;
}
A ligação que estou fazendo é especificada assim:
ppr_error_type ppr_detect_objects (ppr_context_type context,
ppr_image_type image,
ppr_object_list_type *object_list);
Minha chamada C# se parece com a seguinte:
ObjectInfo info = new ObjectInfo();
int objOK = ppr_detect_objects(context, imagePtr, ref info);
Eu sei que o ppr_object_list_type espera preencher uma matriz de objetos. E eu sei que C# tem problemas com matrizes de objetos aninhados. Eu estava pensando que a maneira como estou fazendo isso retornaria apenas o primeiro (o que é tudo o que me preocupo).
No entanto, quando eu chamo dessa maneira "num_objects" é preenchido corretamente com um valor de 1. O modelo_ID está errado (parece um endereço de memória) e tudo o mais é zeros.
Qualquer ajuda é apreciada. Eu fiz muitas estruturas de trabalho de trabalho para não gerenciar o código, mas nunca qualquer coisa remotamente esse complexo.
Solução
ppr_object_list_type
contém a ponteiro para um ppr_object_type
, não um real ppr_object_type
valor.
Você precisa mudar ObjectInfo
para
[StructLayout(LayoutKind.Sequential)]
public struct ObjectInfo
{
public int numObjects;
public IntPtr objListPointer;
}
Para acessar o ObjectType
valores, você precisará usar os métodos no Marechal classe.
Outras dicas
Isso deve funcionar se você se preocupa apenas com o primeiro item:
public struct ObjectInfo
{
public int numObjects;
[MarshalAs(UnmanagedType.LPArray, SizeConst = 1)]
public ObjectType[] objListPointer;
}