C++/CLI String Conversions - string

I found this really nice piece of code that converts a string to a System:String^ as in:
System::String^ rtn = gcnew String(move.c_str()); // 'move' here is the string
I'm passing rtn back to a C# program. Anyways, inside the function where this code exists, I'm passing in a System::String^. I also found some code to convert a System:String^ to a string using the following code:
pin_ptr<const wchar_t> wch = PtrToStringChars(cmd); // 'cmd' here is the System:String
size_t convertedChars = 0;
size_t sizeInBytes = ((cmd->Length + 1) * 2);
errno_t err = 0;
char *ch = (char *)malloc(sizeInBytes);
err = wcstombs_s(&convertedChars,ch, sizeInBytes,wch, sizeInBytes);
Now I can use 'ch' as a string.
This, however, seems to be alot more work than converting the other way using the gcnew. So, at last my question is, is there something out there that will convert a System::String^ to string using a similar fashion as with the gcnew way?

Use VC++'s marshaling library: Overview of Marshaling in C++
#include <msclr/marshal_cppstd.h>
// given System::String^ mstr
std::string nstr = msclr::interop::marshal_as<std::string>(mstr);

this could be useful:
wchar_t *str = "Hi StackOverflow"; //native
String^ mstr= Marshal::PtrToStringAnsi((IntPtr)str); // native to safe managed
wchar_t* A=( wchar_t* )Marshal::StringToHGlobalAnsi(mstr).ToPointer(); // return back to native
don't forget using namespace System::Runtime::InteropServices;

Related

How to convert AnsiString to std::string in C++ Builder?

I would like to ask how can I get a text input from TEdit control and cast it to std::string (not AnsiString).
For example, if I have a TEdit control with the name User, I get the text from it with the User->Text command. What I want to do is to assign that value to a std::string, for example string my_str = User->Text;.
I would like to ask, how can I do this in C++ Builder? Is there some sort of a ToString() method or sort of, because I was not able to find one.
In C++Builder 2007 and earlier, TEdit::Text is an 8-bit AnsiString in the user's default ANSI locale. It is very straight forward to convert an AnsiString to a std::string - just use the AnsiString::c_str() method to get a null-terminated char* pointer to the AnsiString data, and then you can assign that to the std::string, eg:
std::string my_str = User->Text.c_str();
/* or:
System::AnsiSystem text = User->Text;
std::string my_str(text.c_str(), text.Length());
*/
If you want the std::string data to be in another character encoding, such as UTF-8, then you will have to convert the AnsiString data accordingly, such as with MultiByteToWideChar()/WideCharToMultiByte(), UTF8Encode(), etc, before assigning it to the std::string.
In C++Builder 2009 and later, TEdit::Text is a 16-bit UnicodeString in UTF-16 format. The easiest way to convert a UnicodeString to a std::string is to first convert to an AnsiStringT<CP> (where CP is the desired ANSI codepage - AnsiString uses CP=0, UTF8String uses CP=65001, etc), and then convert that to std::string, eg:
std::string my_str = AnsiString(User->Text).c_str(); // or UTF8String, etc...
/* or:
System::AnsiString text = User->Text; // or UTF8String, etc...
std::string my_str(text.c_str(), text.Length());
*/
Alternatively, in C++11 and later, you can convert the UnicodeString to a std::wstring first, and then use std::wstring_convert, eg:
#include <locale>
std::wstring my_wstr = User->Text.c_str();
/* or:
System::UnicodeString text = User->Text;
std::wstring my_wstr(text.c_str(), text.Length());
*/
// System::Char may be either wchar_t or char16_t, depending
// on which platform you are compiling for...
std::string my_str = std::wstring_convert<std::codecvt_utf8_utf16<System::Char>>{}.to_bytes(my_wstr);
I had a lot of those to migrate from Borland to Embarcadero Rio. So I created a method to do it.
#include <cwchar.h> //std::wcslen
char* __fastcall AnsiOf(wchar_t* w)
{
static char c[STR_CONV_BUF_SIZE];
memset(c, 0, sizeof(c));
WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, w, std::wcslen(w), c, STR_CONV_BUF_SIZE, NULL, NULL);
return c;
}
std::string my_str = AnsiOf((User->Text).c_str());

Changing the text of a C++ CLI label

I am trying to change the text of a label in a C++ CLI program. I need to take a value the the user entered in a textbox, insert that into a short string, then change a label to that string. I have no problem constructing the string, but I am having trouble setting the label to the new string. Here is my code...
std::string v1str = "Phase A: ";
v1str.append(vt2); //vt2 is type str::string
v1str.append(" Vac");
label->Text = v1str;
This is the error message that I'm getting...
Why am I not allowed to pass v1str as the label text setter? How can I pass the string I've constructed to the label text setter?
Label::Text has a type of System::String^, which is a managed .Net string object. You cannot assign a std:string to a System::String^ directly becuase they are different types.
You can convert a std::string to a System::String. However you most likely just want to use the System::String type directly:
System::String^ v1str = "Phase A: ";
v1st += vt2; // or maybe gcnew System::String(vt2.c_str());
v1str += " Vac";
label->Text = v1str;
C++/CLI is not C++, you can't use std::string in there. But you can use C++ within C++/CLI, and convert std::string to and from System::String
//In C++/CLI form:
#include <vcclr.h>
System::String^ clr_sting = "clr_sting";
//convert strings from CLI to C++
pin_ptr<const wchar_t> cpp_string = PtrToStringChars(clr_sting);
//convert strings from C++ to CLI
System::String^ str = gcnew System::String(cpp_string);
//or
std::string std_string = "std_string";
System::String^ str2 = gcnew System::String(std_string.c_str());

C++ Convert Sytem::String^ to LPCOLESTR

I write in mixed mode (C++/CLI) and I can not resolve this problem:
String ^progID = "Matrikon.OPC.Server";
CLSID clsid;
HRESULT result = CLSIDFromProgID(progID, &clsid);
error C2664: 'CLSIDFromProgID' : cannot convert parameter 1 from 'System::String ^' to 'LPCOLESTR'
How can I convert String^ to LPCOLESTR ?
Thanks!
I made another way:
// 1.
pin_ptr<const WCHAR> str = PtrToStringChars(progID);
LPCOLESTR coleString = (LPWSTR)str;
I have found that pin_ptr will be released if goes out of scope Define the Scope of Pinning Pointers and pin_ptr (C++/CLI)
This code works well for me:
// 2. this is the same like (1.)
String ^progID2 = "Matrikon.OPC.Simulation.1";// This is example of dynamic string
pin_ptr<const WCHAR> PINprogID2 = PtrToStringChars(progID2);
CLSID clsid2;
HRESULT result2 = CLSIDFromProgID(PINprogID2, &clsid2); //(LPCOLESTR, &CLSID)
Another example:
// 3.
pin_ptr<const WCHAR> sclsid3 = PtrToStringChars("{63D5F432-CFE4-11d1-B2C8-0060083BA1FB}");
CLSID clsid3;
CLSIDFromString((WCHAR*)sclsid3, &clsid3); //(LPOLESTR, &CLSID)
I am not much experienced and I am not sure if there are some lack of memory, but I think those codes are correct.
Avoid using the hammer for every nail. C++/CLI lets you just as easily use native types. So it is simply:
LPCOLESTR progid = L"Matrikon.OPC.Server";
// etc..
Non-zero odds (always say why) that you can simply use Type::GetTypeFromProgID().
First, lets convert System::String to char*
IntPtr p = Marshal::StringToHGlobalAnsi(progID);
char *pNewCharStr = static_cast<char*>(p.ToPointer());
second, casting char * to LPCOLESTR using ATL conversion macro:
LPCOLESTR converted_string = A2COLE(pNewCharStr);

Convert a String^ to wstring C++

I programmed a little Application in C++. There is a ListBox in the UI. And I want to use the selected Item of ListBox for an Algorithm where I can use only wstrings.
All in all I have two questions:
-how can I convert my
String^ curItem = listBox2->SelectedItem->ToString();
to a wstring test?
-What means the ^ in the code?
Thanks a lot!
It should be as simple as:
std::wstring result = msclr::interop::marshal_as<std::wstring>(curItem);
You'll also need header files to make that work:
#include <msclr\marshal.h>
#include <msclr\marshal_cppstd.h>
What this marshal_as specialization looks like inside, for the curious:
#include <vcclr.h>
pin_ptr<WCHAR> content = PtrToStringChars(curItem);
std::wstring result(content, curItem->Length);
This works because System::String is stored as wide characters internally. If you wanted a std::string, you'd have to perform Unicode conversion with e.g. WideCharToMultiByte. Convenient that marshal_as handles all the details for you.
I flagged this as a duplicate, but here's the answer on how to get from System.String^ to a std::string.
String^ test = L"I am a .Net string of type System::String";
IntPtr ptrToNativeString = Marshal::StringToHGlobalAnsi(test);
char* nativeString = static_cast<char*>(ptrToNativeString.ToPointer());
The trick is make sure you use Interop and marshalling, because you have to cross the boundary from managed code to non-managed code.
My version is:
Platform::String^ str = L"my text";
std::wstring wstring = str->Data();
With Visual Studio 2015, just do this:
String^ s = "Bonjour!";
C++/CLI
#include <vcclr.h>
pin_ptr<const wchar_t> ptr = PtrToStringChars(s);
C++/CX
const wchart_t* ptr = s->Data();
According to microsoft:
Ref How to: Convert System::String to Standard String
You can convert a String to std::string or std::wstring, without using PtrToStringChars in Vcclr.h.
// convert_system_string.cpp
// compile with: /clr
#include <string>
#include <iostream>
using namespace std;
using namespace System;
void MarshalString ( String ^ s, string& os ) {
using namespace Runtime::InteropServices;
const char* chars =
(const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();
os = chars;
Marshal::FreeHGlobal(IntPtr((void*)chars));
}
void MarshalString ( String ^ s, wstring& os ) {
using namespace Runtime::InteropServices;
const wchar_t* chars =
(const wchar_t*)(Marshal::StringToHGlobalUni(s)).ToPointer();
os = chars;
Marshal::FreeHGlobal(IntPtr((void*)chars));
}
int main() {
string a = "test";
wstring b = L"test2";
String ^ c = gcnew String("abcd");
cout << a << endl;
MarshalString(c, a);
c = "efgh";
MarshalString(c, b);
cout << a << endl;
wcout << b << endl;
}
output:
test
abcd
efgh

strstream in c++

I am writing the code
#include<sstream>
#include<iostream>
using namespace std;
int main(){
strstream temp;
int t =10;
temp>>10;
string tt ="testing"+temp.str();
Have a problem, it does not work at all for the temp variable, just get in result only string testing without 10 in the end?
}
You should use operator<<() instead, temp << 10;.
The problem looks (to me) like a simple typo. You need to replace: temp>>10; with temp<<10;.
As you have included sstream, I think you had the ostringstream class in mind.
ostringstream temp;
int i = 10;
temp << i;
string tt = "testing" + temp.str();
To use strstream, include <strstream>. strstream work with char*, which are C strings. Use ostringstream to work with objects of type basic_string.

Resources