Red Gate forums :: View topic - Problems calling VC++ dll from C#
Return to www.red-gate.com RSS Feed Available

Search  | Usergroups |  Profile |  Messages |  Log in  Register 
Go to product documentation
PInvoke.Net
PInvoke.Net forum

Problems calling VC++ dll from C#

Search in PInvoke.Net forum
Post new topic   Reply to topic
Jump to:  
Author Message
AndyG



Joined: 14 Jan 2009
Posts: 2

PostPosted: Wed Jan 14, 2009 7:27 pm    Post subject: Problems calling VC++ dll from C# Reply with quote

Hi

I'm struggling to call a legacy API from C#.

One of the calls I need to make takes a structure that contains, amongst other things, lots of fixed length char arrays.

I thought that I'd managed to create a matching definition in my C# code but when I debug the legacy API, all of the elements of the structure that are fixed length char arrays appear with a null terminator (character 0) as the last character - this has overwritten my actual last character of the string.

I based the C# structures on the document "Default Marshaling for Strings" (http://msdn.microsoft.com/en-us/library/s9ts558h(VS.85).aspx).

Here is an example of the first two elements of the structure. The legacy api struct definition starts with

typedef
struct CLASS_EXPORT SoeMstItem
{
char ORDNUM [ 6];
char CUSTID [ 7];

(Note that this may have a #pragma pack (4) before the definition).


The C# struct definition starts as

[StructLayout(LayoutKind.Sequential)]
internal struct SoeMstItem
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
internal string ORDNUM; // 6
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 7)]
internal string CUSTID; // 7

When I set up the structure, I do the following

SoeMstItem header = new SoeMstItem();
header.ORDNUM = "123456";
header.CUSTID = "1234567";

When I get into the legacy api in the VC++ debugger, ORDNUM is set to "12345" + character 0 and CUSTID is set to "123456" + character 0. So the buffers are the correct length but the marshalling appears to have done something with null terminated strings.

Does anyone have any suggestions about where I'm going wrong?
Thanks in advance
Andy
Back to top
View user's profile Send private message
AndyG



Joined: 14 Jan 2009
Posts: 2

PostPosted: Thu Jan 15, 2009 1:41 am    Post subject: Reply with quote

After a few more hours playing around, the only way that I have found to make this work is to declare the elements of the structure as follows

[StructLayout(LayoutKind.Sequential)]
internal struct SoeMstItem
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst=6)]
internal byte [] ORDNUM;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=7)]
internal byte [] CUSTID;

Then set the values with

header.ORDNUM = StrToByteArray("123456");
header.CUSTID = StrToByteArray("1234567");

public static byte[] StrToByteArray(string str)
{
System.Text.ASCIIEncoding encoding=new System.Text.ASCIIEncoding();
return encoding.GetBytes(str);
}


This is not exactly pleasant as I need to remember to pad each string out to it's correct length with spaces otherwise I get marshalling exceptions.

A simpler solution would be helpful if anyone can assist.
Thanks
Andy
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic All times are GMT + 1 Hour
Page 1 of 1

 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group