Why is a "char *" method parameter being projected as a "sbyte *"?

  • Thread starter Thread starter Chip Gore
  • Start date Start date
C

Chip Gore

Hi -

I know that this is most likely a Microsoft-ism, but none the less...

I have a C++ class


namespace JELLO {

public ref class DEMO
{
public:
DEMO() {;}
~DEMO() {;}

bool DoStuff(const char *s1, char *s2)
{
int a = 1;
}
};
}

And when I try and call this from "C-Sharp-Land", I'm being told that
my s1 and s2 are of type "sbyte *", and I'm not sure how to get a C#
"string" to be able to be passed in to my DEMO::DoStuff() method.

I'm certain that this is just my brain having a fit over nothing, but
I'm starting to think my computer doesn't like me anymore.

Can someone please point me to the bloody obvious that I'm not seeing?

Thanks
 
[...]
And when I try and call this from "C-Sharp-Land", I'm being told that
my s1 and s2 are of type "sbyte *", and I'm not sure how to get a C#
"string" to be able to be passed in to my DEMO::DoStuff() method.

Short, useless answer: in C#, the "char" type is Unicode, 2 bytes per
character. A C++ "char" is in fact the same as a C# "sbyte" (signed byte).

What you really want to know is how to get .NET strings to play nice with
C++ strings ("char" arrays). Depending on what your C++ code is doing,
you either need to just use .NET strings (i.e. instances of "String") in
your managed C++ code, or you need to marshal between the .NET String
class and your C++ strings. Here's an MSDN page that might be a good
starting point:http://msdn2.microsoft.com/en-us/library/bb384865.aspx

In this newsgroup, Ben, Willy, and maybe one or two others, might have an
answer to your question. But this is a perfect example of the sort of
question that is completely on-topic in the
microsoft.public.dotnet.framework.interop newsgroup. In that forum, they
are doing this sort of thing on a regular basis and you'll get the best,
most complete answers posting in that newsgroup.

Pete

Thanks for the feedback, I'll re-post the request in the interop
newsgroup
 
You need to marshall the .NET Unicode string to an unmanaged single-byte
string as your function is expecting - see the
System.Runtime.InteropServices.Marshal class. You would do something like:

IntPtr ptr;
try
{
ptr = Marshal.StringToHGlobalAnsi(mystring);
DEMO::DoStuff( (char*)ptr );
}
finally
{
if (ptr != IntPtr.Zero) Marshal.FreeHGlobal(ptr); // Don't forget to
free it!
}

I've always done it that way, although I know you can also use the
MarshalAsAttribute - you may want to look at that too.

HTH
 
You need to marshall the .NET Unicode string to an unmanaged single-byte
string as your function is expecting - see the
System.Runtime.InteropServices.Marshal class. You would do something like:

IntPtr ptr;
try
{
ptr = Marshal.StringToHGlobalAnsi(mystring);
DEMO::DoStuff( (char*)ptr );}

finally
{
if (ptr != IntPtr.Zero) Marshal.FreeHGlobal(ptr); // Don't forget to
free it!

}

I've always done it that way, although I know you can also use the
MarshalAsAttribute - you may want to look at that too.

HTH

Boy oh boy does that LOOK like what I want, now if I can just get my C+
+ code to marshal back correctly, I might have a shot at this :-D
 
See Marshal.PtrToStringAnsi(IntPtr)

Chip Gore said:
Boy oh boy does that LOOK like what I want, now if I can just get my C+
+ code to marshal back correctly, I might have a shot at this :-D
 
Chip said:
[...]
And when I try and call this from "C-Sharp-Land", I'm being told
that my s1 and s2 are of type "sbyte *", and I'm not sure how to
get a C# "string" to be able to be passed in to my DEMO::DoStuff()
method.

Short, useless answer: in C#, the "char" type is Unicode, 2 bytes per
character. A C++ "char" is in fact the same as a C# "sbyte" (signed
byte).

What you really want to know is how to get .NET strings to play nice
with C++ strings ("char" arrays). Depending on what your C++ code
is doing, you either need to just use .NET strings (i.e. instances
of "String") in your managed C++ code, or you need to marshal
between the .NET String class and your C++ strings. Here's an MSDN
page that might be a good starting
point:http://msdn2.microsoft.com/en-us/library/bb384865.aspx

In this newsgroup, Ben, Willy, and maybe one or two others, might
have an answer to your question. But this is a perfect example of
the sort of question that is completely on-topic in the
microsoft.public.dotnet.framework.interop newsgroup. In that forum,
they are doing this sort of thing on a regular basis and you'll get
the best, most complete answers posting in that newsgroup.

Pete

Thanks for the feedback, I'll re-post the request in the interop
newsgroup

Actually, because you are using the C++/CLI compiler,
microsoft.public.dotnet.languages.vc is the most appropriate place to
discuss this.

To be useful from C# and other .NET languages, the member functions of your
ref class should accept parameters of type System::String^. The C++/CLI
compiler provides some pretty simple methods for getting the data as native
C++ characters if you need to, for example the PtrToStringChars function.
 
I have written a managed wrapper for c++ function to be called from C#. For Ex:
Code:

const char * Cmd::ManagedWrapper::SaveLog()
{
const char * str = "COMMAND EXECUTED SUCCESSFULLY.";
return str;
}


I am calling this function from C#.
Code:
ManagedWrapper wrp = new ManagedWrapper();
sbyte* str = wrp.SaveLog();

I get the error message:
Pointers and fixed size buffers may only be used in an unsafe context.

I want to get this string ""COMMAND EXECUTED SUCCESSFULLY." in C#.
Can anyone help?
 
I have written a managed wrapper for c++ function to be called from C#. For Ex:
Code:

const char * Cmd::ManagedWrapper::SaveLog()
{
const char * str = "COMMAND EXECUTED SUCCESSFULLY.";
return str;
}


I am calling this function from C#.
Code:
ManagedWrapper wrp = new ManagedWrapper();
sbyte* str = wrp.SaveLog();

I get the error message:
Pointers and fixed size buffers may only be used in an unsafe context.

I want to get this string ""COMMAND EXECUTED SUCCESSFULLY." in C#.
Can anyone help?
 
I have written a managed wrapper for c++ function to be called from C#. For Ex:
Code:

const char * Cmd::ManagedWrapper::SaveLog()
{
const char * str = "COMMAND EXECUTED SUCCESSFULLY.";
return str;
}


I am calling this function from C#.
Code:
ManagedWrapper wrp = new ManagedWrapper();
sbyte* str = wrp.SaveLog();

I get the error message:
Pointers and fixed size buffers may only be used in an unsafe context.

I want to get this string ""COMMAND EXECUTED SUCCESSFULLY." in C#.

You should have the managed C++ return a System::String which
is a C# string.

Try:

String^ Cmd::ManagedWrapper::SaveLog()
{
const char * str = "COMMAND EXECUTED SUCCESSFULLY.";
return gcnew String(str);
}

Arne

PS: You should have created a new thread instead of replying
to an old thread.
 
Back
Top