Char* in C++ 6 to C# .Net [modified]
-
Hi Guys, I have a DLL created in Visual Studio 6 / C++ with the following function
MyDLL_API int __stdcall MyMethod( char *strA, char *strB, char *strC )
i am trying to reference it like so in c# 2005
[DllImport("mydll.dll", CharSet = CharSet.Auto)]
public static extern int MyMethod(ref string strA, ref string strB, ref string strC);Here is the debugging code i added to MyMethod but the params are garbage when presented on screen:
MyDLL_API int __stdcall MyMethod( char *strA, char *strB, char *strC )
int ret_val = 0;
char cA[161] = {0};
char cB[161] = {0};
char cC[161] = {0};
LPSTR buffer = NULL;
char cMsg[161] = {0};buffer = (LPSTR)strA; strncpy( cA, buffer, 161); buffer = (LPSTR)strB; strncpy( cB, buffer, 161); buffer = (LPSTR)strC; strncpy( cC, buffer, 161); sprintf( cMsg, "Params A=%s,B=%s,C=%s", strA, strB, strC ); MessageBox( NULL, cMsg, "Dispense", MB\_OK );
the function gets called but all i see is garbage in the parameters passed in, other than a string what else can i use to pass to the Char*? Thanks In Advance
modified on Tuesday, March 22, 2011 10:29 AM
-
Hi Guys, I have a DLL created in Visual Studio 6 / C++ with the following function
MyDLL_API int __stdcall MyMethod( char *strA, char *strB, char *strC )
i am trying to reference it like so in c# 2005
[DllImport("mydll.dll", CharSet = CharSet.Auto)]
public static extern int MyMethod(ref string strA, ref string strB, ref string strC);Here is the debugging code i added to MyMethod but the params are garbage when presented on screen:
MyDLL_API int __stdcall MyMethod( char *strA, char *strB, char *strC )
int ret_val = 0;
char cA[161] = {0};
char cB[161] = {0};
char cC[161] = {0};
LPSTR buffer = NULL;
char cMsg[161] = {0};buffer = (LPSTR)strA; strncpy( cA, buffer, 161); buffer = (LPSTR)strB; strncpy( cB, buffer, 161); buffer = (LPSTR)strC; strncpy( cC, buffer, 161); sprintf( cMsg, "Params A=%s,B=%s,C=%s", strA, strB, strC ); MessageBox( NULL, cMsg, "Dispense", MB\_OK );
the function gets called but all i see is garbage in the parameters passed in, other than a string what else can i use to pass to the Char*? Thanks In Advance
modified on Tuesday, March 22, 2011 10:29 AM
Just an update on this, I found that if i do the following in C#
[DllImport("mydll.dll", CharSet = CharSet.Auto)]
public static extern int MyMethod(
[param: MarshalAs(UnmanagedType.VBByRefStr)]
ref string strA,
[param: MarshalAs(UnmanagedType.VBByRefStr)]
ref string strB,
[param: MarshalAs(UnmanagedType.VBByRefStr)]
ref string strC);That my messagebox in MyMethod in the dll shows the first character of the strings eg passing 1, 234, 5 the results are A=1,B=2,C=5
-
-
Thanks Richard, I cant modify the dll as its from a third party and they just sent me on a samepl of the code they use how would I go about adding a front end converter from WCHAR to CHAR? Thanks In Advance
Just write your own C/C++ function that interfaces to the C# code and takes the three strings and converts them from Unicode to
char
using the WideCharToMultiByte()[^] function. You can then pass the converted strings to the DLL routines.I must get a clever new signature for 2011.
-
Just an update on this, I found that if i do the following in C#
[DllImport("mydll.dll", CharSet = CharSet.Auto)]
public static extern int MyMethod(
[param: MarshalAs(UnmanagedType.VBByRefStr)]
ref string strA,
[param: MarshalAs(UnmanagedType.VBByRefStr)]
ref string strB,
[param: MarshalAs(UnmanagedType.VBByRefStr)]
ref string strC);That my messagebox in MyMethod in the dll shows the first character of the strings eg passing 1, 234, 5 the results are A=1,B=2,C=5
That sounds about right as the Unicode characters for these values are the same as ANSI. However, because the Unicode are 2-byte characters, and the second byte in these cases will be zero, you effectively see a 1 character string in each parameter.
I must get a clever new signature for 2011.
-
That sounds about right as the Unicode characters for these values are the same as ANSI. However, because the Unicode are 2-byte characters, and the second byte in these cases will be zero, you effectively see a 1 character string in each parameter.
I must get a clever new signature for 2011.
Hi Richard, Thanks for all the help. After playing around with a few other things i found that this works
[DllImport("MyDll.dll", CharSet = CharSet.Unicode)]
public static extern int MyMethod(
[param: MarshalAs(UnmanagedType.LPStr)]
StringBuilder strA,
[param: MarshalAs(UnmanagedType.LPStr)]
StringBuilder strB,
[param: MarshalAs(UnmanagedType.LPStr)]
StringBuilder strC);changeg need were to remove the ref keyword, changes string to stringbuilder and the unmanaged type to LPStr
-
Just an update on this, I found that if i do the following in C#
[DllImport("mydll.dll", CharSet = CharSet.Auto)]
public static extern int MyMethod(
[param: MarshalAs(UnmanagedType.VBByRefStr)]
ref string strA,
[param: MarshalAs(UnmanagedType.VBByRefStr)]
ref string strB,
[param: MarshalAs(UnmanagedType.VBByRefStr)]
ref string strC);That my messagebox in MyMethod in the dll shows the first character of the strings eg passing 1, 234, 5 the results are A=1,B=2,C=5
I'm no expert on C++ interfacing, so I'd defer to Richard on this, but I think marshaling as UnmanagedType.LPStr might take care of this. According to the MSDN docs, that'd send them through as single-byte, null-terminated strings. Would eliminate the need to convert from Unicode. EDIT: Never mind, looks like you already figured this out :)
Proud to have finally moved to the A-Ark. Which one are you in?
Author of the Guardians Saga (Sci-Fi/Fantasy novels) -
Hi Guys, I have a DLL created in Visual Studio 6 / C++ with the following function
MyDLL_API int __stdcall MyMethod( char *strA, char *strB, char *strC )
i am trying to reference it like so in c# 2005
[DllImport("mydll.dll", CharSet = CharSet.Auto)]
public static extern int MyMethod(ref string strA, ref string strB, ref string strC);Here is the debugging code i added to MyMethod but the params are garbage when presented on screen:
MyDLL_API int __stdcall MyMethod( char *strA, char *strB, char *strC )
int ret_val = 0;
char cA[161] = {0};
char cB[161] = {0};
char cC[161] = {0};
LPSTR buffer = NULL;
char cMsg[161] = {0};buffer = (LPSTR)strA; strncpy( cA, buffer, 161); buffer = (LPSTR)strB; strncpy( cB, buffer, 161); buffer = (LPSTR)strC; strncpy( cC, buffer, 161); sprintf( cMsg, "Params A=%s,B=%s,C=%s", strA, strB, strC ); MessageBox( NULL, cMsg, "Dispense", MB\_OK );
the function gets called but all i see is garbage in the parameters passed in, other than a string what else can i use to pass to the Char*? Thanks In Advance
modified on Tuesday, March 22, 2011 10:29 AM
Some of the replies you got contain too much attributes IMO. Passing strings between C# and native code is pretty easy, you don't even need all those Marshal thingies, a simple
CharSet = CharSet.Unicode
[ADDED] orCharSet = CharSet.ASCII
[ADDED] in yourDllImport
should do it. You must get rid of theref
keywords obviously, as a string is always passed as a pointer anyway. And if one or more of those strings are meant to be output parameters, the easiest way is by using aStringBuilder
. I think I covered all these essentials in this article[^]. :)Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum
Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.
modified on Tuesday, March 22, 2011 12:32 PM
-
Some of the replies you got contain too much attributes IMO. Passing strings between C# and native code is pretty easy, you don't even need all those Marshal thingies, a simple
CharSet = CharSet.Unicode
[ADDED] orCharSet = CharSet.ASCII
[ADDED] in yourDllImport
should do it. You must get rid of theref
keywords obviously, as a string is always passed as a pointer anyway. And if one or more of those strings are meant to be output parameters, the easiest way is by using aStringBuilder
. I think I covered all these essentials in this article[^]. :)Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum
Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.
modified on Tuesday, March 22, 2011 12:32 PM
Hi Luc, I tried what you said as well but I only get see the first character in the C++ method, here is the code:
[DllImport("MyDll.dll", CharSet = CharSet.Unicode)]
public static extern int MyMethod(
string strA,
string strB,
string strC);I took out the
[param: MarshalAs(UnmanagedType.LPStr)]
but it seems that this is needed
-
Hi Luc, I tried what you said as well but I only get see the first character in the C++ method, here is the code:
[DllImport("MyDll.dll", CharSet = CharSet.Unicode)]
public static extern int MyMethod(
string strA,
string strB,
string strC);I took out the
[param: MarshalAs(UnmanagedType.LPStr)]
but it seems that this is needed
sorry, my mistake, if your native code wants ASCII, just say
CharSet.ASCII
. There is automatic marshaling that will allocate and later free buffers, translate the strings and everything for you. Warning: you are not allowed to remember those string pointers (actually any pointer unless the object remains pinned) and use them after the function return! :)Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum
Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.
-
sorry, my mistake, if your native code wants ASCII, just say
CharSet.ASCII
. There is automatic marshaling that will allocate and later free buffers, translate the strings and everything for you. Warning: you are not allowed to remember those string pointers (actually any pointer unless the object remains pinned) and use them after the function return! :)Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum
Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.
-
Hi Richard, Thanks for all the help. After playing around with a few other things i found that this works
[DllImport("MyDll.dll", CharSet = CharSet.Unicode)]
public static extern int MyMethod(
[param: MarshalAs(UnmanagedType.LPStr)]
StringBuilder strA,
[param: MarshalAs(UnmanagedType.LPStr)]
StringBuilder strB,
[param: MarshalAs(UnmanagedType.LPStr)]
StringBuilder strC);changeg need were to remove the ref keyword, changes string to stringbuilder and the unmanaged type to LPStr