C++ char array to C# string, weird characters

S

scottelloco

Hi,

I currently have a C++ dll that's passing a struct to a C# application.
Everything is working except for the char array member in the struct.
When I look at the values in the C# app when debugging all I see are a
few square "control-type" characters. The way I'm doing this is based
on the MSDN documentation and posts I've seen from users in the group.
The folloing is a sample of my code. I've tried using both CharSet.Auto
and CharSet.UniCode on my struct and function definitions, but receive
the same results either way.

I would appreciate any assitance.

Thanks, -Scott


C++ code
--------------
struct tblProcedure
{
unsigned long ProcedureId;
unsigned long InstitutionId;
char FName[56];
char LName[56];
}

CEDBXML_API bool LoadProcedure(tblProcedure* procedure)
{
procedure->ProcedureId = 810;
procedure->InstitutionId = 2002;
memcpy(procedure->FName, "Michael", sizeof("Michael"));
memcpy(procedure->LName, "Houser", sizeof("Houser"));
}

extern "C"
{
CEDB_API bool LoadProcedure(tblProcedure* tblProc);
}


C# code
---------------
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct tblProcedure
{
public int ProcedureId;
public int AttendingId;
public int InstitutionId;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 56)]
public string FName;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 56)]
public string LName;
};



[DllImport("CedbXml", CharSet = CharSet.Auto)]
public static extern bool LoadProcedure(ref
CEDBProcedures.tblProcedure Procs);

tblProcedure procobj = new tblProcedure();

CeDbApi.LoadProcedure(ref procobj);

----------------------------------------------
At this point procobj.FName and procobj.LName just basically have a
bunch of garbage in them when I look at the values in the debugger.

I would appreciate any ideas.

Thanks, -Scott
 
S

scottelloco

I accidently added the "public int AttendingId; " to the C#
struct in my example. It shouldn't be there. The C# struct is actually
as follows:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct tblProcedure
{
public int ProcedureId;
public int InstitutionId;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 56)]
public string FName;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 56)]
public string LName;
};

Thanks, -Scott
 
S

scottelloco

Btw, I've tried this on both a Windows CE 4.2 and 5.0 device running
the .NET CF 2.0

Thanks, -Scott
 
P

Paul G. Tobey [eMVP]

One word: Unicode. Understand it; love it.

You've declared your C structure as containing, not Unicode (16-bit)
characters, but ASCII (8-bit) characters. C# doesn't understand that, so
you've told the two languages to interpret the same data as two different
things. C# is looking at each pair of characters in the C string and
treating that pair as the two halves of one Unicode character. Declare
those arrays as TCHAR in C and it will probably work (assuming you set them
up correctly with Unicode strings, instead of ASCII strings. _tcscpy(
procedure->FName, _T( "Michael" ) ) )

Paul T.
 
S

scottelloco

Thanks Paul.

I mistakenly assumed that the interop functionality in .NET could do
the marshalling between the ASCII chracters in C++ and the Unicode that
..NET requires.

Thanks for your help.

-Scott
 
G

Guest

Native code in CE uses Unicode as well, so the marshaler *does* handle moves
strings properly. The marshaler has no way of knowing that you're using
ASCII and so it assumes that you're doing things by normal conventions.

-Chris
 

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