How to use UTF8Encoding in Visual C++ - c++

I need to change the below c# code to c++ code.
public static byte[] StrToByteArray(string str)
{
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
return encoding.GetBytes(str);
}
on this website i found the c++ code for UTF8Encoding from which i created this code
void StrToByteArray(string unicodeString)
{
UTF8Encoding^ utf8 = gcnew UTF8Encoding;
array<Byte>^encodedBytes = utf8->GetBytes( unicodeString );
}
but this gives me the following error
Error 2 error C2664: 'cli::array
^System::Text::Encoding::GetBytes(cli::array
^)' : cannot convert parameter 1 from
'std::string' to
'cli::array
Why would it do this while it is identical to the documentation? (except i am using a normal string, but using a top level string^ gives me an error on that.)
i'm not sure if it is related but my code is managed.
note: i tried not worrying yet about returning any data till i get this working.

string is a different data type in C++ as it is in C#. Try using System::String^ instead.

Related

How LoadString() works in VC++?

I am working on an MFC application where when I write Something like this:CString sName; sName.LoadString(IDS_NAME_STRING) it works fine but when I try to write while initializing in one line like CString sName = sName.LoadString(IDS_NAME_STRING), I am getting error
Error C2440 'initializing': cannot convert from 'BOOL' to 'ATL::CStringT<char,StrTraitMFC_DLL<char,ATL::ChTraitsCRT<_CharType>>>'
I am not getting what's wrong with the latter statement. Can anyone help me to understand this error?
CString::LoadString returns a value of type BOOL. That's what the error message is telling you. It turned out to be a bit longer as it includes the full template instantiations. It's ultimately saying
cannot convert from 'BOOL' to 'CString'
The solution is what you already have:
CString sName;
sName.LoadString(IDS_NAME_STRING);
If you'd rather have that as a single statement, you'll have to implement a function for it, e.g.
CString load_string(uint32_t id) {
CString s;
s.LoadString(id);
return s;
}
With that you can write
auto s = load_string(IDS_NAME_STRING);
Note that the function load_string mirrors the behavior of the initial code: If a string resource with any given ID cannot be found, it returns an empty string. If you'd rather have failure communicated to clients you could throw an exception.

C++ make::shared wrapping on existing raw pointer

I am working on a small wrapper for an FMOD library. Below is a snippet of the code that I have, and there are other libraries that manage the SoundData class:
class SoundData
{
public:
...
std::string mSoundName;
std::shared_ptr<FMOD::Sound> mFmodSoundHandle;
...
}
void SoundLib::CreateSound(SoundData& data)
{
FMOD::Sound *sound = nullptr;
system->createSound(data.mSoundName.data(), FMOD_DEFAULT, nullptr, &sound);
data.mFmodSoundHandle = std::make_shared<FMOD::Sound>(sound);
}
Trying to compile this snippet of the code, I get this error:
Error C2664 'FMOD::Sound::Sound(const FMOD::Sound &)': cannot convert argument 1 from 'FMOD::Sound *' to 'const FMOD::Sound &' SoundLib ...\MSVC\14.29.30133\include\xutility 158
I cannot quite understand if I am using std::make_shared() in the wrong way here? The goal here is to save the output from createSound() that is passed as a sound variable into the structure SoundData. Variable data will be managed afterwards.
You're passing a pointer where you should pass a reference. Try *sound.
Notice that you're not wrapping a pointer, you're creating a new instance of Sound and copying the value of *sound into it.
To wrap it consider:
data.mFmodSoundHandle.reset(sound);

COM : convert 'const GUID*' to const wchar_t*

I am porting some code from VS to mingw C++ . One of the statements in my code is
CFactoryTemplate g_Templates[1] = {
{&CLSID_SystemClock, CSystemClock::CreateInstance}
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
I am getting the following error on the first statement
error: cannot convert 'const GUID* {aka const _GUID*}' to 'const
WCHAR* {aka const wchar_t*}' in initialization
I am completely puzzled by this. I did a little investigation and noticed that
CFactoryTemplate is a class in combase.h . Also my project is UNICODE enabled if that matters. Any suggestions on how to resolve this issue ?
Your code - you say you are porting is wrong, you need to provide different parameters to CFactoryTemplate, the compiler error proves that. Here you will find some sample code to init such array of instances of this class (you dont need to fill all fields):
// list of class ids and creator functions for class factory
CFactoryTemplate g_Templates[2]=
{ { L"Gargle filter" // CFactoryTemplate.m_name
, &CLSID_Gargle // CFactoryTemplate.m_ClsID
, CGargle::CreateInstance // CFactoryTemplate.m_lpfnNew
, NULL // CFactoryTemplate.m_lpfnInit
, &sudGargle // CFactoryTemplate.m_pAMovieSetup_Filter
}
, { L"Gargle filter property page"
, &CLSID_GargProp
, CGargleProperties::CreateInstance
}
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
from https://msdn.microsoft.com/en-us/library/aa451506.aspx
also Hans Passant has given you other example

Error C2440 '=' : cannot convert from 'cli::array<Type> ^' to 'wchar_t'

I got a little problem with my C++/CLI progamm.
I got a few Char arrays wo work without problems.
Header1:
ref class _CGuid{
static const int CIDGR=37;
public:
array<Char>^ cGuid;
array<Char>^ cUuid;
}
Cpp1 -> contruktor:
cGuid = gcnew array<Char>(CIDGR);
some function:
_CGuid::Type(String^ tmpname,String^ tmpid)
{
pcName=tmpname;
cUuid=tmpid->ToCharArray();
}
So this Works Perfectly fine for me without errors.
How ever This doesn’t work:
Other Header:
ref class CStorage{
public:
array<String^>^ names;
array<Char>^ mac;
Other contruktor
names = gcnew array<String^>(100);
mac = gcnew array<Char>(100);
some function 2:
names[k]=tname;
mac[k]=tmac->ToCharArray(); <-------- Error Line
k++;
This line gets the error:
error C2440: '=' : cannot convert from cli::array<Type> ^ to wchar_t
with
[
Type=wchar_t
]
There is no context in which this conversion is possible
So I really don´t know whats the problem here.
The error says it all, actually. ToCharArray returns an array<Char>, which you try to assign to a single Char (= wchar_t) when accessing mac[k].
Did you maybe mean to assign to mac instead?
mac = tmac->ToCharArray();
If so, then this line is redundant:
mac = gcnew array<Char>(100);
Here you allocate memory for mac which you later throw away when you re-assign mac.
here you copy a CLI array coming from the "ToCharArray" in 1 wchar_t of the Mac array!
mac[k]=tmac->ToCharArray(); <-------- Error Line
as you want an array of Mac Address you must allocate it with
mac = gcnew array<array<Char> >(100);
so now you can affect mac[k]

Error when passing a 'system::string' to a function

I have the following function, which will hopefully tell me whether or not a folder exists, but when I call it, I get this error -
cannot convert parameter 1 from 'System::String ^' to 'std::string'
The function -
#include <sys/stat.h>
#include <string>
bool directory_exists(std::string path){
struct stat fileinfo;
return !stat(path.c_str(), &fileinfo);
}
The call (from the form.h file that holds the form where the user selects the folder) -
private:
System::Void radioListFiles_CheckedChanged(System::Object^ sender, System::EventArgs^ e) {
if(directory_exists(txtActionFolder->Text)){
this->btnFinish->Enabled = true;
}
}
Is anyone able to tell me how to filx this? Thanks.
You're trying to convert from a managed, C++/CLI string (System::String^) into a std::string. There is no implicit conversion provided for this.
In order for this to work, you'll have to handle the string conversion yourself.
This will likely look something like:
std::string path = context->marshal_as<std::string>(txtActionFolder->Text));
if(directory_exists(path)) {
this->btnFinish->Enabled = true;
}
That being said, in this case, it might be easier to stick to managed APIs entirely:
if(System::IO::Directory::Exists(txtActionFolder->Text)) {
this->btnFinish->Enabled = true;
}
You are trying to convert a CLR string to a STL string to convert it to a C-string to use it with a POSIX-emulation function. Why such a complication? Since you are using C++/CLI anyway, just use System::IO::Directory::Exists.
To make this work you need to convert from the managed type System::String to the native type std::string. This involves a bit of marshaling and will result in 2 separate string instances. MSDN has a handy table for all of the different types of marshaling for strings
http://msdn.microsoft.com/en-us/library/bb384865.aspx
In this particular case you can do the following
std::string nativeStr = msclr::interop::marshal_as<std::string>(managedStr);