C# string to C++ dll char*

J

johnsto

I'm really stuck - can someone help me!

I've got a basic setup consisting of two things:
1. A C# web service
2. An unmanaged C++ DLL

The WS is intended to call some functions in the DLL. The DLL has some
legacy code which requires char* in its method parameters.

I also have a new file in the DLL which is basically an intermediary -
the WS can call the exported functions from this file, which then call
the legacy code. The problem is converting from the native C# strings in
the WS to the char*'s in the C++ code.

So, the WS calls method(string) in the DLL, and the DLL then needs to
call method(char*) in its C++ code, where string==char*.

At the moment I have the DLL exporting method(String*)'s, but of course
in C# I can't get the address of a string to pass to the method. If I
change the DLL methods to method(String) (ie. no pointer), the compiler
complains that they HAVE to be pointers. I can't use method(char*)
either because then I'm back to the original problem of C# not wanting
to call a method with a char* in it.

Help!
 
S

Shakir Hussain

For char*, you have to do this

byte [] str = new byte [255];

Pass str to the function
 
C

Chris R. Timmons

I'm really stuck - can someone help me!

I've got a basic setup consisting of two things:
1. A C# web service
2. An unmanaged C++ DLL

The WS is intended to call some functions in the DLL. The DLL
has some legacy code which requires char* in its method
parameters.

I also have a new file in the DLL which is basically an
intermediary - the WS can call the exported functions from this
file, which then call the legacy code. The problem is converting
from the native C# strings in the WS to the char*'s in the C++
code.

So, the WS calls method(string) in the DLL, and the DLL then
needs to call method(char*) in its C++ code, where
string==char*.

At the moment I have the DLL exporting method(String*)'s, but of
course in C# I can't get the address of a string to pass to the
method. If I change the DLL methods to method(String) (ie. no
pointer), the compiler complains that they HAVE to be pointers.
I can't use method(char*) either because then I'm back to the
original problem of C# not wanting to call a method with a char*
in it.

You can use the either the System.String or System.Text.StringBuilder
class. The underlying P/Invoke marshalling code in the .Net
framework will do all of the messy character pointer conversions for
you. If the string parameter is used as an output or input/output
buffer, then use StringBuilder. Otherwise if the string parameter is
input-only you can use the String class.

For example, the Win32 API function GetPrivateProfileString has both
input-only string parameters, and a string output parameter. Here's
how it can be accessed in C# using the String and StringBuilder
classes as parameter types:

/* Original C Method Signature:

DWORD GetPrivateProfileString(
LPCTSTR lpAppName,
LPCTSTR lpKeyName,
LPCTSTR lpDefault,
LPTSTR lpReturnedString,
DWORD nSize,
LPCTSTR lpFileName
);

*/

[DllImport("kernel32", EntryPoint="GetPrivateProfileString",
SetLastError = false, CharSet = CharSet.Auto)]
private static extern long GetPrivateProfileString(
string lpApplicationName, // in
string lpKeyName, // in
string lpDefault, // in
StringBuilder lpReturnedString, // out
int nSize, // in
string lpFileName); // in


public string GetIniValue(
string iniFileName,
string sectionName,
string keyName,
string defaultValue)
{
const int maxlen = 255;

StringBuilder sBuffer = new StringBuilder(maxlen);

// The P/Invoke marshaller takes care of converting the
// String and StringBuilder parameters to/from
// character pointers.

GetPrivateProfileString(sectionName, keyName, defaultValue,
sBuffer, maxlen, iniFileName);

return sBuffer.ToString();
}
 
J

johnsto

Chris said:
You can use the either the System.String or System.Text.StringBuilder
class. The underlying P/Invoke marshalling code in the .Net
framework will do all of the messy character pointer conversions for
you. If the string parameter is used as an output or input/output
buffer, then use StringBuilder. Otherwise if the string parameter is
input-only you can use the String class.

It is input-only... so you're saying if I pass it a System::String, it
will convert to a char* automatically?

I mean, the very basic version of the problem is converting the
System::String to char*, and working out where to do the conversion. The
C++ requires char*, the C# WS needs String (it makes life complicated
and complains about char*), and the DLL intermediary is there really
just to forward method calls and handle any parameter conversion.

Part of the problem is actually convincing the C# bit to let me use
String* as a pointer - which I can then pass to the DLL... That's the
last hurdle that got me before I gave up for the weekend...

Argh!!!
 
B

BMermuys

Hi,

johnsto said:
I'm really stuck - can someone help me!

I've got a basic setup consisting of two things:
1. A C# web service
2. An unmanaged C++ DLL

The WS is intended to call some functions in the DLL. The DLL has some
legacy code which requires char* in its method parameters.

I also have a new file in the DLL which is basically an intermediary -
the WS can call the exported functions from this file, which then call
the legacy code. The problem is converting from the native C# strings in
the WS to the char*'s in the C++ code.

So, the WS calls method(string) in the DLL, and the DLL then needs to
call method(char*) in its C++ code, where string==char*.

The dll (intermediary) that WS suppose to call, is it a managed c dll or a
plain old c dll ? Because that's still not very clear here.


HTH,
greetings
 
C

Chris R. Timmons

It is input-only... so you're saying if I pass it a
System::String, it will convert to a char* automatically?
Yes.

I mean, the very basic version of the problem is converting the
System::String to char*, and working out where to do the
conversion. The C++ requires char*, the C# WS needs String (it
makes life complicated and complains about char*), and the DLL
intermediary is there really just to forward method calls and
handle any parameter conversion.

Part of the problem is actually convincing the C# bit to let me
use String* as a pointer - which I can then pass to the DLL...
That's the last hurdle that got me before I gave up for the
weekend...

Are you trying to use a "string *" in the C# code? Just try a plain
old System.String. If that doesn't work, try
System.Text.StringBuilder. I don't think there's any need to use
pointers (*) in the C# code.

To see why, look at the example code I posted. The C "LPSTR"
parameter type means "Long Pointer to STRing", which is a typedef for
"char *". And LPCSTR means "Long Pointer to a Const STRing", which
is a typedef for "const char *" (see WTypes.h for the
actual typedefs). The P/Invoker marshaller correctly translates from
System.String to LPCSTR, and from System.Text.StringBuilder to LPSTR.
 
J

johnsto

BMermuys said:
Hi,

The dll (intermediary) that WS suppose to call, is it a managed c dll or a
plain old c dll ? Because that's still not very clear here.

It's unmanaged - I think it was throwing up errors as a managed DLL (due
to the legacy stuff). I guess that makes it 'plain old c' although I'm
building it with VS2003.
 
B

BMermuys

johnsto said:
It's unmanaged - I think it was throwing up errors as a managed DLL (due
to the legacy stuff). I guess that makes it 'plain old c' although I'm
building it with VS2003.

ok, no problem, then you have to follow Chris' replies.

Greetings
 
J

johnsto

Chris said:
To see why, look at the example code I posted. The C "LPSTR"
parameter type means "Long Pointer to STRing", which is a typedef for
"char *". And LPCSTR means "Long Pointer to a Const STRing", which
is a typedef for "const char *" (see WTypes.h for the
actual typedefs). The P/Invoker marshaller correctly translates from
System.String to LPCSTR, and from System.Text.StringBuilder to LPSTR.

Damn, .NET is so smart :)
 

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