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!
byte [] str = new byte [255];
Pass str to the function
--
Shak
(Houston)
"johnsto" <any...@anywhere.com> wrote in message
news:cddlmm$fac$1...@titan.btinternet.com...
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();
}
--
Hope this helps.
Chris.
-------------
C.R. Timmons Consulting, Inc.
http://www.crtimmonsinc.com/
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!!!
"johnsto" <any...@anywhere.com> wrote in message
news:cddlmm$fac$1...@titan.btinternet.com...
> 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
> Chris R. Timmons wrote:
>> 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?
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.
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
Damn, .NET is so smart :)