By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,507 Members | 1,200 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,507 IT Pros & Developers. It's quick & easy.

C struct to C# mapping

P: n/a
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?


Feb 6 '06 #1
Share this Question
Share on Google+
11 Replies


P: n/a
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

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Feb 6 '06 #2

P: n/a
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" <ma********************@mvps.org> wrote in message
news:uE**************@TK2MSFTNGP09.phx.gbl...
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

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.

Feb 6 '06 #3

P: n/a
"Mattias Sjögren" <ma********************@mvps.org> wrote in message
news:uE**************@TK2MSFTNGP09.phx.gbl...
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)]
Feb 6 '06 #4

P: n/a
>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

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Feb 6 '06 #5

P: n/a
>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

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Feb 6 '06 #6

P: n/a

"Mattias Sjögren" <ma********************@mvps.org> wrote in message
news:Oj**************@tk2msftngp13.phx.gbl...
The struct is still not filled with data.
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 see that a sizeof( SGMINFO) i C is 255 bytes,
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,
and Marshal.SizeOf(typeof( SGMINFO )) in .Net is 344 bytes.
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}
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

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.

Feb 6 '06 #7

P: n/a
Sorry for the changed user name, but I'm at home.
"Mattias Sjögren" <ma********************@mvps.org> wrote in message
news:Oj**************@tk2msftngp13.phx.gbl...
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

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.

Feb 6 '06 #8

P: n/a
>[ 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.

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,


Then your value for strLONG must be wrong.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Feb 6 '06 #9

P: n/a

"Mattias Sjögren" <ma********************@mvps.org> wrote in message
news:O1*************@TK2MSFTNGP12.phx.gbl...
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
Feb 7 '06 #10

P: n/a
>> 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?


No, the InAttribute and OutAttribute classes.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Feb 7 '06 #11

P: n/a
Mattias,
Tanks for very good help!

"Mattias Sjögren" <ma********************@mvps.org> wrote in message
news:%2****************@TK2MSFTNGP14.phx.gbl...
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?


No, the InAttribute and OutAttribute classes.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.

Feb 11 '06 #12

This discussion thread is closed

Replies have been disabled for this discussion.