C struct to C# mapping

T

Tor Aadnevik

Hi,

I'm trying to call a win32 function using pinvoke and C# .Net.

The function takes a struct reference as a parameter (lpInfo), but on return
the struct is not filled with data, and I'm suspecting that I have made a
mistake mapping up the struct.



DBSTAT DBenum ( XInt32 hDBase,

LPSTR lpszPath,

XDWORD nLevel,

DBENUMCB Callback,

DWORD UserData,

LPVOID lpInfo);



The C struct is like this (truncated):

typedef struct _seginfo {

CHAR Name [ strSHORT + 1 ];

CHAR Desc [ strLONG + 1 ];

DWORD Created;

WORD DClass;

WORD UType;

Int32 Top;

Int32 Bottom;

WORD wPoints;

FLOAT fHStart;

WORD uHUnit;

FLOAT fVScale;

WORD SmpSize; // for smpFILE = file size

// for smpREGULAR

WORD TixPerSmp;

// for smpRANGE

XDWORD *lpUpdateCount;

// any

Int32 lAliasOffset;

} SGMINFO;



strSHORT = 10;

strLONG = 256;

Can anyone help me with a correct C# mapping?
 
M

Mattias Sjögren

Tor,
Can anyone help me with a correct C# mapping?

I'm guessing it should look something like this

struct SGMINFO
{
[MmshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string Name;
[MmshalAs(UnmanagedType.ByValTStr, SizeConst=257
public string Desc;
public uint Created;
public ushort DClass;
public ushort UType;
public int Top;
public int Bottom;
public ushort wPoints;
public float fHStart;
public ushort uHUnit;
public float fVScale;
public ushort SmpSize;
public ushort TixPerSmp;
public IntPtr lpUpdateCount;
public int lAliasOffset;
}


Mattias
 
T

Tor Aadnevik

Hi Mattias,
Thanks for your answer!

The struct is still not filled with data.
I see that a sizeof( SGMINFO) i C is 255 bytes, and Marshal.SizeOf(
typeof( SGMINFO )) in .Net is 344 bytes.
Maybe this is due to the fact that a char in ansi C is 1 byte wheras a char
in C# is 2 bytes?
Or do you think this is not the case?

Regards Tor



Mattias Sjögren said:
Tor,
Can anyone help me with a correct C# mapping?

I'm guessing it should look something like this

struct SGMINFO
{
[MmshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string Name;
[MmshalAs(UnmanagedType.ByValTStr, SizeConst=257
public string Desc;
public uint Created;
public ushort DClass;
public ushort UType;
public int Top;
public int Bottom;
public ushort wPoints;
public float fHStart;
public ushort uHUnit;
public float fVScale;
public ushort SmpSize;
public ushort TixPerSmp;
public IntPtr lpUpdateCount;
public int lAliasOffset;
}


Mattias
 
J

James Park

Mattias Sjögren said:
Tor,
Can anyone help me with a correct C# mapping?

I'm guessing it should look something like this

struct SGMINFO
{
[MmshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string Name;
[MmshalAs(UnmanagedType.ByValTStr, SizeConst=257
public string Desc;
public uint Created;
public ushort DClass;
public ushort UType;
public int Top;
public int Bottom;
public ushort wPoints;
public float fHStart;
public ushort uHUnit;
public float fVScale;
public ushort SmpSize;
public ushort TixPerSmp;
public IntPtr lpUpdateCount;
public int lAliasOffset;
}

I think it needs a StructLayoutAttribute:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
 
M

Mattias Sjögren

I think it needs a StructLayoutAttribute:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]

That's the default for C# structs so it's optional. You don't have to
add it but it doesn't change anything if you do.


Mattias
 
M

Mattias Sjögren

The struct is still not filled with data.

How are you using it?

I see that a sizeof( SGMINFO) i C is 255 bytes,

I find that hard to believe since the Desc field alone is 257 bytes.

and Marshal.SizeOf(typeof( SGMINFO )) in .Net is 344 bytes.

I get 312 or 308 depending on the packing.

Maybe this is due to the fact that a char in ansi C is 1 byte wheras a char
in C# is 2 bytes?

The size of a char to the marshaler is whatever you set with the
StructLayout attribute. If you keep the default (CharSet.Ansi) it's
one byte per character.


Mattias
 
T

Totto

Mattias Sjögren said:
How are you using it?
public delegate bool EnumCallbackCB( string EnumName, uint UserData );
[ DllImport( "WDBase.dll", CharSet=CharSet.Auto, EntryPoint="DBenumA",
SetLastError=true, ExactSpelling=true )]
public static extern WarriorCommon.DBStat DBEnum( UInt32 DBHandler, string
Path, Int32 Level, EnumCallbackCB Callback, Int32 SizeOfUserData, ref
SGMINFO sgm );
I find that hard to believe since the Desc field alone is 257 bytes.
Dont understand it, I checked again and sizeof(SGMINFO) is only 244 in C,
I get 312 or 308 depending on the packing.
Sorry I did't mention that the struct was truncated. The complete listing
goes like this

[ StructLayout( LayoutKind.Sequential )]
public struct SGMINFO{
[[MarshalAs(UnmanagedType.ByValTStr, SizeConst=11)]
public string Name;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=257)]
public string Desc;
public uint Created;//DWORD
public uint Modified;//DWORD
public uint Code;//DWORD
public ushort bIsAliased;//WORD
public ushort SType;//WORD
public ushort DType;//WORD
public ushort DClass;//WORD
public ushort UType;//WORD
public int Top;//Int32
public int Bottom;//Int32
public ushort wPoints;//WORD
public float fHStart;//FLOAT
public float fHStep;//FLOAT
public ushort uHUnit;//WORD
public float fVScale;//FLOAT
public float fVMin;//FLOAT
public float fVMax;//FLOAT/
public ushort SmpSize;
public ushort TixPerSmp;//WORD
public ushort SmpPerBlk;//WORD
public ushort IxPerBlk;//WORD
public IntPtr lpUpdateCount;//XDWORD
public int lAliasOffset;//Int32}
 
M

Mattias Sjögren

[ DllImport( "WDBase.dll", CharSet=CharSet.Auto, EntryPoint="DBenumA",
SetLastError=true, ExactSpelling=true )]
public static extern WarriorCommon.DBStat DBEnum( UInt32 DBHandler, string
Path, Int32 Level, EnumCallbackCB Callback, Int32 SizeOfUserData, ref
SGMINFO sgm );

You may have to add the attributes [In, Out] to the last parameter to
get changes to marshal back.

Dont understand it, I checked again and sizeof(SGMINFO) is only 244 in C,

Then your value for strLONG must be wrong.


Mattias
 
T

Tor Aadnevik

Mattias Sjögren said:
You may have to add the attributes [In, Out] to the last parameter to
get changes to marshal back.

Would that be a MarshalAsAttribute declaration?

Regards
Tor
 
M

Mattias Sjögren

You may have to add the attributes [In, Out] to the last parameter to
Would that be a MarshalAsAttribute declaration?

No, the InAttribute and OutAttribute classes.


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