views:

105

answers:

2

I am trying to call into an unmanaged DLL that has the following structure:

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;

This is what I am using on the C# side:

[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;
    }

The call I am making is specified like this:

ppr_error_type ppr_detect_objects (ppr_context_type context,
                                   ppr_image_type image,
                                   ppr_object_list_type *object_list);

My C# call looks like this:

ObjectInfo info = new ObjectInfo();
int objOK = ppr_detect_objects(context, imagePtr, ref info);

I know that the ppr_object_list_type is expecting to fill in an array of objects. And I know C# has troubles with arbitray arrays of nested objects. I was thinking that the way I am doing it would return just the first one (which is all I care about).

However, when I call it this way "num_objects" is filled in correctly with a value of 1. The model_id is wrong (looks like a memory address) and everything else is zeros.

Any help is appreciated. I have done lots of work passing structures to unmanages code, but never anything remotely this complex.

+1  A: 

ppr_object_list_type contains a pointer to a ppr_object_type, not an actual ppr_object_type value.

You need to change ObjectInfo to

[StructLayout(LayoutKind.Sequential)]
public struct ObjectInfo
{
    public int numObjects;
    public IntPtr objListPointer;
}

To access the ObjectType values, you'll need to use the methods in the Marshal class.

SLaks
Thanks. This was what I was missing. I did this: ObjectType foo = (ObjectType) Marshal.PtrToStructure(objPtr, typeof (ObjectType));It works now.ad
Alex Kilpatrick
A: 

This should work if you only care about the first item:

public struct ObjectInfo
{
    public int numObjects;
    [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)]
    public ObjectType[] objListPointer;
}
Pent Ploompuu