Return reference to Structure from unmanage Code

G

Guest

I have an unmanaged DLL, which includes the following struct :

typedef struct TB_Board_Inf
{
char BoardOwner[20];
WORD BoardId;
BYTE BoardRev; //A,B,C...
} TB_Board_Info_struct;

and the following API :

TB_Board_Info_struct *iTB_BoardInformationBlock_Read( void );
int iTB_BoardInformationBlock_Update(TB_Board_Info_struct *mmBInfo);

in my C# I define the update function as following :

[DllImport("TebInterface.dll",
EntryPoint="iTB_BoardInformationBlock_Update",SetLastError=true,
CharSet=CharSet.Ansi, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
public static extern int iTB_BoardInformationBlock_Update(ref
TB_Board_Info_struct mmBInfo);

But I don't know how to define the Read , since I got an error in 'ref' :
[DllImport("TebInterface.dll",
EntryPoint="iTB_BoardInformationBlock_Read",SetLastError=true,
CharSet=CharSet.Ansi, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
public static extern ref TB_Board_Info_struct
iTB_BoardInformationBlock_Read();

How to define the Read ? I also define the structure as :

[ StructLayout( LayoutKind.Sequential ,CharSet = CharSet.Ansi)]
public struct TB_Board_InformationBlock_struct
{
public IntPtr BoardOwner ; //MAX = 20
public Int16 BoardId;
public byte BoardRev; //A,B,C...
}

Regards,
Yosef
 
M

Mattias Sjögren

How to define the Read ?

Make the return type an IntPtr and call Marshal.PtrToStructure to
dereference the pointer.

public struct TB_Board_InformationBlock_struct
{
public IntPtr BoardOwner ; //MAX = 20
public Int16 BoardId;
public byte BoardRev; //A,B,C...
}

BoardOwner shouldn't be an IntPtr, the array is inline in the struct.
Make it something like

[MarshalAs(UnmanagedType.ByValArray, SizeConst=20)]
public byte[] BoardOwner;



Mattias
 
G

Guest

The data is not correct after Marshal:

C dll :

TB_BInfo_struct *iTB_BoardInformationBlock_Read()
{
TB_BInfo_struct *mmBInfo=NULL;
TB_BoardInformationBlock_Read(&mmBInfo); // allocate struct by using
new
return mmBInfo;
}


C#:

[DllImport("TebInterface.dll",
EntryPoint="iTB_BoardInformationBlock_Read",SetLastError=true,
CharSet=CharSet.Ansi, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
public static extern IntPtr iTB_BoardInformationBlock_Read();


then C#:

//Marshal PTR to TB_BInfo_struct
public TB_BInfo_struct get_structFromIntPtr(IntPtr ptrStruct)
{
TB_BInfo_struct myTB_BInfo_struct= new TB_BInfo_struct();
object a = Marshal.PtrToStructure(ptrStruct,myTB_BInfo_struct.GetType());
return (TB_BInfo_struct)a;
}


TB_BInfo_struct myTB_BInfo_struct;

//read the struct fro DLL then marshal the PTR to TB_BInfo_struct
myTB_BInfo_struct =
this.get_structFromIntPtr(iTB_BoardInformationBlock_Read());

myTB_BInfo_struct properties include garbage values

what is wrong in this code ???????????? Why I get a garbage data ???????


Regards
[Joe]

Mattias Sjögren said:
How to define the Read ?

Make the return type an IntPtr and call Marshal.PtrToStructure to
dereference the pointer.

public struct TB_Board_InformationBlock_struct
{
public IntPtr BoardOwner ; //MAX = 20
public Int16 BoardId;
public byte BoardRev; //A,B,C...
}

BoardOwner shouldn't be an IntPtr, the array is inline in the struct.
Make it something like

[MarshalAs(UnmanagedType.ByValArray, SizeConst=20)]
public byte[] BoardOwner;



Mattias
 
M

Mattias Sjögren

TB_BoardInformationBlock_Read(&mmBInfo); // allocate struct by using

If you allocate the memory with operator new, you need to provide a
function to delete it when you're done with it as well.

what is wrong in this code ???????????? Why I get a garbage data ???????

Not sure. You have to verify that your managed struct declaration
matches the native one, including things like packing.


Mattias
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top