Groups | Blog | Home
all groups > dotnet interop > january 2006 >

dotnet interop : marshalling pointers to classes in C#


marc joanisse
1/29/2006 2:01:02 PM
Hi Folks,
I am writing a c# app that interacts with some scientific hardware (a
"bird", which is just a magnetic tracker) through a C++ DLL. The
procedure birdGetFrame(), reads data from the hardware. The second
parameter a pointer to the struct BIRDFRAME, into which all
the data are written when the procedure returns successfully. BIRDFRAME
itself contains variables of other struct types as you can see below.

When I call the procedure, I get an unhandled exception with the
following error: "Can not marshal parameter #2: The type definition of
this type has no layout information."

It seems that even though I crate a new variable "pframe" of type
BIRDFRAME the procedure cannot pass a pointer to it. I can't tell if
the problem is how I set up pframe, or whether the BIRDFRAME struct is
itself poorly constructed. Any help is appreciated.

I've included the listing of the relevant code below.

-Marc-

Listing:

[DllImport("bird.dll", EntryPoint = "birdGetFrame",
CharSet=CharSet.Auto,SetLastError=true)]
static extern bool birdGetFrame(int nGroupID,
[MarshalAs(UnmanagedType.LPStruct)] ref BIRDFRAME pFrame);

// Bird position structure
public class BIRDPOSITION
{
short nX; // x-coordinate
short nY; // y-coordinate
short nZ; // z-coordinate

}

// Bird angles structure
public class BIRDANGLES
{
short nAzimuth; // azimuth angle
short nElevation; // elevation angle
short nRoll; // roll angle

}

// Bird matrix structure
public class BIRDMATRIX
{
short[,] n= new short [3,3]; // array of matrix
elements

}

// Bird quaternion structure
public class BIRDQUATERNION
{
short nQ0; // q0
short nQ1; // q1
short nQ2; // q2
short nQ3; // q3

}

// Bird reading structure
public class BIRDREADING
{
BIRDPOSITION position; // position of receiver
BIRDANGLES angles; // orientation of
receiver, as angles
BIRDMATRIX matrix; // orientation of
receiver, as matrix
BIRDQUATERNION quaternion; // orientation of receiver, as
quaternion
short wButtons; // button states

}

// Bird frame structure
public class BIRDFRAME
{
int dwTime; // time at which readings were taken, in
msecs
[MarshalAs(UnmanagedType.LPStruct)]
BIRDREADING[] reading = new BIRDREADING [BIRD_MAX_DEVICE_NUM
+ 1];
// reading from each bird

}

// code to read data from bird

BIRDFRAME pframe = new BIRDFRAME();

birdGetFrame(0, ref pframe); // **** error occurs here ****
Mattias Sjögren
1/31/2006 12:43:43 AM
[quoted text, click to view]

It would help to see the original C++ definitions as well.

You may have to change your classes to structs to make them behave
properly when used as a membe in another type.


[quoted text, click to view]

You can't use UnmanagedType.LPStruct this way. And if you're using
v1.x of the .NET framework you can't have struct arrays inside another
type at all, the marshaler doesn't support that.


Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Lee Crabtree
3/9/2006 3:30:10 PM
Have you solved this problem? I've got a similar error while trying to
marshal an unmanaged pointer into a managed class.

Lee Crabtree

[quoted text, click to view]
AddThis Social Bookmark Button