String* to char[] | | |
How the heck does one convert a String* to char[]? Specifically:
String* my_string = "HELLO" ;
char m_char_array[32+1] ;
m_char_array = my_string ; // error
strcpy( m_char_array, my_string ) ; // error
strcpy( m_char_array, my_string.ToCharArray( ) ) ; // error
strcpy( m_char_array, my_string.ToCharArray(0,32 ) ) ; // error
strcpy( m_char_array, my_string.ToCharArray(0,0) ) ; // error
Thanks in advance! : )
[==Peteroid==] | | | | re: String* to char[]
"Peteroid" <peter_oliphant@msn.com> wrote in message
news:%236BZ7FWFFHA.3416@TK2MSFTNGP09.phx.gbl...[color=blue]
> How the heck does one convert a String* to char[]? Specifically:
>
> String* my_string = "HELLO" ;
> char m_char_array[32+1] ;
> ...[/color]
First pin the sting object (prevent it from being moved by the GC), and get
a pointer to the first character of the string
#include <vcclr.h>
wchar_t __pin *p = PtrToStringChars(my_string);
then for as many characters as you have got, copy them to the target
Regards,
Will | | | | re: String* to char[]
Hi Will,
Thanks for the reply. The following line:
wchar_t __pin *p = PtrToStringChars(my_string);
now generates the error: "p is an undeclared indentifier (error C2065)". I
did include the 'vcclr.h' include. I've never used pinning before, though I
vaguely know what it's for (GC can move things around in memory, pin
prevents this, just not sure yet when this is necessary and when it isn't).
Also, I'm trying to get the result into a char[33] array, so is wchar_t*
compatible with this for direct copying?
Also, when you say 'copy them to target' (i.e., the char[33] variable) could
you give me an idea how to do this (e.g., use strcpy?). Thanks again! :)
[==Peteroid==]
PS - It's weird that String* my_string = "HELLO" ; works (i.e. direct
assignment from a char string to a String) but the reverse doesn't (probably
because char came before String* in C(++) laguage development). But it
really shouldn't be this complicated to get a char[] copied to a String
(IMHO), as the requirement for such a conversion to make old code using
char[] more easily modernizable (i.e., String should have come with a built
in conversion tool, which I thought was the purpose of ToCharArray() (which
seems to not do what it looks like it should be doing, as what it outputs
does not act like a char[])...
"William DePalo [MVP VC++]" <willd.no.spam@mvps.org> wrote in message
news:OEA6DLWFFHA.548@TK2MSFTNGP14.phx.gbl...[color=blue]
> "Peteroid" <peter_oliphant@msn.com> wrote in message
> news:%236BZ7FWFFHA.3416@TK2MSFTNGP09.phx.gbl...[color=green]
>> How the heck does one convert a String* to char[]? Specifically:
>>
>> String* my_string = "HELLO" ;
>> char m_char_array[32+1] ;
>> ...[/color]
>
> First pin the sting object (prevent it from being moved by the GC), and
> get a pointer to the first character of the string
>
> #include <vcclr.h>
>
> wchar_t __pin *p = PtrToStringChars(my_string);
>
> then for as many characters as you have got, copy them to the target
>
> Regards,
> Will
>
>
>
>
>[/color] | | | | re: String* to char[]
Peteroid wrote:[color=blue]
> How the heck does one convert a String* to char[]? Specifically:
>
> String* my_string = "HELLO" ;[/color]
HGLOBAL hg = (HGLOBAL)System::Marshal::StringToHGlobalAnsi(my_s tring);
char* p = GlobalLock(hg);
// work with p - it's an ordinary pointer to zero-terminated string
GlobalFree(hg);
-cd | | | | re: String* to char[]
I think you mean
System::Runtime::InteropServices::Marshal::StringT oHGlobalAnsi(my_string);
mosimu
"Carl Daniel [VC++ MVP]" wrote:
[color=blue]
> Peteroid wrote:[color=green]
> > How the heck does one convert a String* to char[]? Specifically:
> >
> > String* my_string = "HELLO" ;[/color]
>
> HGLOBAL hg = (HGLOBAL)System::Marshal::StringToHGlobalAnsi(my_s tring);
> char* p = GlobalLock(hg);
>
> // work with p - it's an ordinary pointer to zero-terminated string
>
> GlobalFree(hg);
>
> -cd
>
>
>[/color] | | | | re: String* to char[]
Peteroid wrote:
[color=blue]
> How the heck does one convert a String* to char[]? Specifically:
>
> String* my_string = "HELLO" ;
> char m_char_array[32+1] ;[/color]
String contains wchar_ts. You may use String::ToCharArray and copy
wchar_t character by character to a wstring, using wstring::push_back().
--
Ioannis Vranos | | | | re: String* to char[]
"Peteroid" <peter_oliphant@msn.com> wrote in message
news:exnDoydFFHA.3824@TK2MSFTNGP10.phx.gbl...[color=blue]
> I've never used pinning before, though I vaguely know what it's for (GC
> can move things around in memory, pin prevents this, just not sure yet
> when this is necessary and when it isn't).[/color]
Well, on the managed side of things you needn't worry about it. The .Net
Platform exists so that developers don't have to work about such things if
they don't want. (We'll agree to table the discussion as to when memory
pressure might become an issue in managed code <g>). However, anytime you
cross the boundary and play in an unmanaged space you have to pin things.
That's because it is possible that the GC can move or reclaim an object
rendering your pointer quite stale. As Martha might say, that would be a bad
thing.
[color=blue]
> Also, I'm trying to get the result into a char[33] array, so is wchar_t*
> compatible with this for direct copying?[/color]
Well, no. Net strings are composed of 16 bit characters.
[color=blue]
> Also, when you say 'copy them to target' (i.e., the char[33] variable)
> could you give me an idea how to do this (e.g., use strcpy?). Thanks
> again! :)[/color]
Actually, it would take sonmething like wcstombs() to transform 16 bit
characters to 8 bit characters.
Carl offered another approach which allocates a unmanaged array of ANSI
characters. You do need to remember to free the handle when you are done or
a memory leak results. For the odd transition into unmanaged code I doubt
that performance implications of the heap allocations are a consideration.
If you are doing a lot of transitions you might want to profile which
approach costs less.
Regards,
Will | | | | re: String* to char[]
mosimu wrote:[color=blue]
> I think you mean
>
> System::Runtime::InteropServices::Marshal::StringT oHGlobalAnsi(my_string);[/color]
yep.
-cd | | | | re: String* to char[]
Ioannis Vranos wrote:
[color=blue]
> String contains wchar_ts. You may use String::ToCharArray and copy
> wchar_t character by character to a wstring, using wstring::push_back().[/color]
Or better:
#using <mscorlib.dll>
#include <string>
int main()
{
using namespace std;
using namespace System;
String *S= __gc new String("Some string");
wchar_t __pin *temp= &(S->ToCharArray())[0];
wchar_t *p=temp;
wstring s(p, p+3);
temp=0;
}
--
Ioannis Vranos | | | | re: String* to char[]
Carl Daniel [VC++ MVP] wrote:
[color=blue][color=green]
>>System::Runtime::InteropServices::Marshal::Strin gToHGlobalAnsi(my_string);[/color][/color]
Why this shouldn't work?
#using <mscorlib.dll>
#include <string>
int main()
{
using namespace std;
using namespace System;
String *S= __gc new String("Some string");
wchar_t __pin *temp= &(S->ToCharArray())[0];
wchar_t *p=temp;
wstring s(p, p+3);
temp=0;
}
--
Ioannis Vranos | | | | re: String* to char[]
Ioannis Vranos wrote:
[color=blue]
> #using <mscorlib.dll>
>
> #include <string>
>
> int main()
> {
> using namespace std;
> using namespace System;
>
> String *S= __gc new String("Some string");
>
> wchar_t __pin *temp= &(S->ToCharArray())[0];
>
> wchar_t *p=temp;
>
> wstring s(p, p+3);
>
> temp=0;
> }[/color]
I used *p, because there is some bug in VC++ 2003 that doesn't compile
wstring s(temp, temp+3); directly. In VC++ 2005 Beta however it works
and with the new C++/CLI syntax it becomes:
#include <string>
int main()
{
using namespace std;
using namespace System;
String ^S= gcnew String("Some string");
pin_ptr<wchar_t> pinp= &(S->ToCharArray())[0];
wstring s(pinp, pinp+3);
pinp=nullptr;
}
--
Ioannis Vranos | | | | re: String* to char[]
Ioannis Vranos wrote:[color=blue]
> Carl Daniel [VC++ MVP] wrote:
>[color=green][color=darkred]
>>> System::Runtime::InteropServices::Marshal::StringT oHGlobalAnsi(my_string);[/color][/color]
>
>
> Why this shouldn't work?[/color]
I think it should.
The OP wanted a narrow string though, not a std::wstring.
-cd | | | | re: String* to char[]
Yes, i did something very similar:
char char_array[32+1] ;
String* string_thing = new String("Hello") ;
for ( int c=0 ; c < length ; c++)
{
char_array[c] = char(string_thing->chars[c]) ;
}
char_array[length] = '\0' ;
After this code is executed: char_array contains null-terminated "Hello".
Thanx for everyones help! my code now works... :)
[==Peteroid==]
"Ioannis Vranos" <ivr@remove.this.grad.com> wrote in message
news:OY03OiiFFHA.628@TK2MSFTNGP15.phx.gbl...[color=blue]
> Carl Daniel [VC++ MVP] wrote:
>[color=green][color=darkred]
>>>System::Runtime::InteropServices::Marshal::Stri ngToHGlobalAnsi(my_string);[/color][/color]
>
>
> Why this shouldn't work?
>
>
> #using <mscorlib.dll>
>
> #include <string>
>
> int main()
> {
> using namespace std;
> using namespace System;
>
> String *S= __gc new String("Some string");
>
> wchar_t __pin *temp= &(S->ToCharArray())[0];
>
> wchar_t *p=temp;
>
> wstring s(p, p+3);
>
> temp=0;
> }
>
>
>
> --
> Ioannis Vranos[/color] | | | | re: String* to char[]
After looking my code over again, I'm wondering if I have to 'pin'
string_thing down during the character-by-character assignment loop.
My code so far has worked without doing this, but as I understand it this is
one of those things where it can bite you at random times based on the
current (and sometimes recent past) situation (i.e., depends on if GC
decides to move it at an inappropriate time or not).
On the other hand, it might be the case that i'm guaranteed that as long as
I stay in the same process (i.e. the same event process) that it can't
change. That is, I don't know if during my execution of the processing of a
single event if my code can be interrupted at any time and this GC object
(i.e., String*) then moved (which could be the whole reason for pinning,
which like I've said, is new to me...hehe).
If I need to do pinning, please tell me so, and possibly modify my code
(below from previous message) to include the pinning. Thanks!
[==Peteroid==]
"Peteroid" <peter_oliphant@msn.com> wrote in message
news:OZDclxtGFHA.904@tk2msftngp13.phx.gbl...[color=blue]
> Yes, i did something very similar:
>
> char char_array[32+1] ;
> String* string_thing = new String("Hello") ; int length = String->Length ;
>
> for ( int c=0 ; c < length ; c++)
> {
> char_array[c] = char(string_thing->chars[c]) ;
> }
>
> char_array[length] = '\0' ;
>
>
> After this code is executed: char_array contains null-terminated "Hello".
>
> Thanx for everyones help! my code now works... :)
>
> [==Peteroid==]
>
> "Ioannis Vranos" <ivr@remove.this.grad.com> wrote in message
> news:OY03OiiFFHA.628@TK2MSFTNGP15.phx.gbl...[color=green]
>> Carl Daniel [VC++ MVP] wrote:
>>[color=darkred]
>>>>System::Runtime::InteropServices::Marshal::Str ingToHGlobalAnsi(my_string);[/color]
>>
>>
>> Why this shouldn't work?
>>
>>
>> #using <mscorlib.dll>
>>
>> #include <string>
>>
>> int main()
>> {
>> using namespace std;
>> using namespace System;
>>
>> String *S= __gc new String("Some string");
>>
>> wchar_t __pin *temp= &(S->ToCharArray())[0];
>>
>> wchar_t *p=temp;
>>
>> wstring s(p, p+3);
>>
>> temp=0;
>> }
>>
>>
>>
>> --
>> Ioannis Vranos[/color]
>
>[/color] | | | | re: String* to char[]
"Peteroid" <peter_oliphant@msn.com> wrote in message
news:eY%23$75tGFHA.1172@TK2MSFTNGP12.phx.gbl...[color=blue]
> After looking my code over again, I'm wondering if I have to 'pin'
> string_thing down during the character-by-character assignment loop.[/color]
No, you don't. If understand correctly, you are spinning a loop in managed
code and accessing a property of a managed object. Whaddya gotta pin, there?
<G>
You need to pin a pointer when you have to convert from a __gc pointer to a
__nogc pointer. __gc pointers point to objects that cam be moved by the
grbage collector. __nogc pointers don't know about the existence of the
grabage collector. They must remain fixed. That's what pinning does.
Regards,
Will | | | | re: String* to char[]
Peteroid wrote:
[color=blue]
> Yes, i did something very similar:
>
> char char_array[32+1] ;[/color]
Why use a char array and not a std::wstring which is the natural for
this, or even std::string?
[color=blue]
> String* string_thing = new String("Hello") ;
>
> for ( int c=0 ; c < length ; c++)
> {
> char_array[c] = char(string_thing->chars[c]) ;[/color]
Besides the correct string_thing->Length that should be used, casting is
not needed here.
--
Ioannis Vranos | | | | re: String* to char[]
Peteroid wrote:
[color=blue]
> After looking my code over again, I'm wondering if I have to 'pin'
> string_thing down during the character-by-character assignment loop.[/color]
No pinning is not needed here. You have to pin only when you are doing
pointer arithmetic on managed types (*p++, etc).
--
Ioannis Vranos | | | | re: String* to char[]
Ioannis Vranos wrote:
[color=blue]
> No pinning is not needed here. You have to pin only when you are doing
> pointer arithmetic on managed types (*p++, etc).[/color]
And not pointer arithmetic only. Also when you point to or access any
part of a managed type with an unmanaged pointer.
--
Ioannis Vranos | | | | re: String* to char[]
Is it safe to write to the the pinned string pointer? Say you call
GetComputerName. Can you pin a String object that is large enough and pass
its LPWSTR to GetComputerName to eliminate the memory copy? Is this legal
with VC2005? It seems PtrToStringChars returns a _const_Char_ptr. Is that to
keep people from writing directly into the String object? Is not there a way
to do it with StringBuilder? Otherwise it seems DllImport can be more
efficient than IJW when calling this type of API.
"Ioannis Vranos" wrote:
[color=blue]
> Ioannis Vranos wrote:
>[color=green]
> > No pinning is not needed here. You have to pin only when you are doing
> > pointer arithmetic on managed types (*p++, etc).[/color]
>
>
> And not pointer arithmetic only. Also when you point to or access any
> part of a managed type with an unmanaged pointer.
>
>
>
> --
> Ioannis Vranos
>[/color] | | | | re: String* to char[]
RC wrote:
[color=blue]
> Is it safe to write to the the pinned string pointer?[/color]
If you are talking about System::String, no. System::String is an
immutable String type, and also it is a high-level type, so if you use a
String object, you had better use its methods, properties, etc.
[color=blue]
> Say you call
> GetComputerName. Can you pin a String object that is large enough and pass
> its LPWSTR to GetComputerName to eliminate the memory copy?[/color]
I do not know what LPWSTR is, and thus I cannot answer this.
[color=blue]
> Is this legal
> with VC2005?[/color]
In C++/CLI you can only pin value types (value classes,managed arrays of
built in types etc).
[color=blue]
> It seems PtrToStringChars returns a _const_Char_ptr. Is that to
> keep people from writing directly into the String object? Is not there a way
> to do it with StringBuilder?[/color]
You can also convert a StringBuilder to a managed wchar_t array, if this
was your question about.
[color=blue]
> Otherwise it seems DllImport can be more
> efficient than IJW when calling this type of API.[/color]
I only know ISO C++ and .NET.
--
Ioannis Vranos | | | | re: String* to char[]
char *GCStringToChar(String __gc *str)
{
if (str == NULL)
{
return NULL;
}
const wchar_t __pin* p = PtrToStringChars(str);
char* result = (char *)malloc((str -> Length + 1) * 2);
wcstombs(result, p, (str -> Length + 1) * 2);
return result;
}
[color=blue]
> How the heck does one convert a String* to char[]? Specifically:
>
> String* my_string = "HELLO" ;
> char m_char_array[32+1] ;
> m_char_array = my_string ; // error
> strcpy( m_char_array, my_string ) ; // error
> strcpy( m_char_array, my_string.ToCharArray( ) ) ; // error
> strcpy( m_char_array, my_string.ToCharArray(0,32 ) ) ; // error
> strcpy( m_char_array, my_string.ToCharArray(0,0) ) ; // error
> Thanks in advance! : )
>
> [==Peteroid==]
>[/color] |  | Similar .NET Framework bytes | | | /bytes/about
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 226,419 network members.
|