const char* returns true in C++ CLI - c++

since yesterday I have been struggling to turn text into label with code from another class, I came to this:
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
TestApp::UI_Error form("test", "test");
Application::Run(% form);
Using the above code, i display a winapi form that receives "test", "test" as 2x const char* on loading, the problem appears when im trying to set the text in labels using these variables
The code looks like this:
public:
UI_Error(const char* errorText, const char* errorCode)
{
InitializeComponent();
this->testLabel->Text = System::Convert::ToString(errorText);
}
For some reason, each time the return value shown in the win forms window is "true", although it should be "test" here, does anyone know the solution?
I tried to use std::string instead of const char*, unfortunately for some reason i get the error code that a static variable is required :(

Maybe I am wrong here, but System::Convert::ToString() seems not to have a method that accepts a const char* pointer. It looks like it gets cast to something else.
Try this instead:
Text = gcnew System::String(errorText);

Related

Handling of const char* on ESP32

I'm working on making some Spotify API calls on an ESP32. I'm fairly new to C++ and while I seem to got it working how I wanted it to, I would like to know if it is the right way/best practice or if I was just lucky. The whole thing with chars and pointers is still quite confusing for me, no matter how much I read into it.
I'm calling the Spotify API, get a json response and parse that with the ArduinoJson library. The library returns all keys and values as const char*
The library I use to display it on a screen takes const char* as well. I got it working before with converting it to String, returning the String with the getTitle() function and converting it back to display it on screen. After I read that Strings are inefficient and best to avoid, I try to cut out the converting steps.
void getTitle()
{
// I cut out the HTTP request and stuff
DynamicJsonDocument doc(1024);
DeserializationError error = deserializeJson(doc, http.getStream(), );
JsonObject item = doc["item"];
title = item["name"]; //This is a const char*
}
const char* title = nullptr;
void loop(void) {
getTitle();
u8g2.clearBuffer();
u8g2.setDrawColor(1);
u8g2.setFont(u8g2_font_6x12_tf);
u8g2.drawStr(1, 10, title);
u8g2.sendBuffer();
}
Is it okay to do it like that?
This is not fine.
When seeing something like this, you should immediately become suspicious.
This is because in getTitle, you are asking a local object (item) for a pointer-- but you use the pointer later, when the item object no longer exists.
That means your pointer might be meaningless once you need it-- it might no longer reference your data, but some arbitrary other bytes instead (or even lead to crashes).
This problem is independent of what exact library you use, and you can often find relevant, more specific information by searching your library documentation for "lifetime" or "object ownership".
FIX
Make sure that item (and also DynamicJsonDocument, because the documentation tells you so!) both still exist when you use the data, e.g. like this:
void setTitle(const char *title)
{
u8g2.clearBuffer();
u8g2.setDrawColor(1);
u8g2.setFont(u8g2_font_6x12_tf);
u8g2.drawStr(1, 10, title);
u8g2.sendBuffer();
}
void updateTitle()
{
DynamicJsonDocument doc(1024);
DeserializationError error = deserializeJson(doc, http.getStream(), );
JsonObject item = doc["item"];
setTitle(item["name"]);
}
See also: https://arduinojson.org/v6/how-to/reuse-a-json-document/#the-best-way-to-use-arduinojson
Edit: If you want to keep parsing/display update decoupled
You could keep the JSON document "alive" for when the parsed data is needed:
/* "static" visibility, so that other c/cpp files ("translation units") can't
* mess mess with our JSON doc directly
*/
static DynamicJsonDocument doc(1024);
static const char *title;
void parseJson()
{
[...]
// super important to avoid leaking memory!!
doc.clear();
DeserializationError error = deserializeJson(doc, http.getStream(), );
// TODO: robustness/error handling (e.g. inbound JSON is missing "item")
title = doc["item"]["name"];
}
// may be nullptr when called before valid JSON was parsed
const char* getTitle()
{
return title;
}

How to modify a Button Content from a function (c++ UWP app)?

Currently learning C++ and using Visual Studio 2017. My UWP app have 10 buttons (named b0-b9) and I want to create a function that will manage the content change of the buttons.
For this I need to pass the button name and the content. I want to modify to the function but I don't know how to do it.
It would look something like this:
void contentButtonChange(Button BtnName, String myString)
{
BntName->Content = myString;
}
Main()
{
.....
contentButtonChange(b0, string1);
contentButtonChange(b1, string2);
contentButtonChange(b2, string3);
.....
}
added note: I'm currently able to change the Content of the button from the Main but I'm unable to write a function that will accept a Button as a parameter. I'm always getting an error no matter what I try.
In the example above BtnName in the function is highlighted with the error: expression must have a pointer or handle type
I found how to do it. I need to add this to my function call:
Windows::UI::Xaml::Controls::Button^ btnName
like this:
void contentButtonChange(Windows::UI::Xaml::Controls::Button^ btnName, Platform::String^ myString)
{
bntName->Content = myString;
}
works now.
You need to use TextBlock to set to the Button.
void contentButtonChange(Button BtnName, string myString)
{
BntName->Content = new TextBlock() { Text = myString };
}

Can't convert QString to Const Char*

I'm new to QT so please excuse me if I'm blatantly doing something wrong here, but I've looked at all the questions here on the matter but can't seem to find something that works. I'm trying to have the user create a folder by entering a name for it, and it 'creates' a folder with the name. I say 'create' because it's not exactly creating one, it makes a folder first called "project" before you enter the name, and when you enter a name it renames it. However, when I try and rename the folder with the inputted name it gives me
error:C2664: 'int rename(const char *,const char *)' : cannot convert
argument 1 from 'QString' to 'const char *'
Here's my code:
void MainWindow::on_actionNew_Project_triggered(const char *parameter)
{
//Create project folder
QString projectPath = "D:/Project";
QDir dir(projectPath);
if (!dir.exists()) {
dir.mkpath(projectPath);
}
//Get project name from user
bool result;
QString name = QInputDialog::getText(0, "New Project",
"Enter in project name", QLineEdit::Normal,
"", &result);
if(result && !name.isEmpty()) {
//Rename project folder to user created name
QDir dir(projectPath);
if (dir.exists()) {
rename(projectPath, name); //Gives me error HERE
}
}
}
I would appreciate it if you guys could help, I've been stuck on this for hours.
You could call QString::toStdString(), and then call c_str() to retrieve the const char* from the std::string.
Your code would look something like this:
if (dir.exists()) {
rename(projectPath.toStdString().c_str(), name);
}
Try dir.rename(dir.dirName(), name);
You are trying to invoke a member function without an instance.
Since rename() is a member function of QDir, you need a QDir instance in order to invoke it. So rather than just calling rename() which invokes who knows what, you need to dir.rename().
QDir::rename() actually takes 2 QStrings as parameters, but that other function you are invoking takes two raw strings, so you don't really need to convert the strings, you were just calling the wrong function.
bool QDir::rename(const QString & oldName, const QString & newName)
You are most likely calling rename() from <stdio.h>, which could also work given that the parameters are correct and the OS can rename the directory, in that case you will need to convert to "raw" C-style strings via yourString.toLatin1().constData(). But since you are using Qt, you might as well use the QDir API, which works directly with QString.
If it still doesn't work, then either your input parameters are wrong, or there is something preventing the OS from rename the directory, for example a file currently in use.
Qt FAQ says:
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QString str1 = "Test";
QByteArray ba = str1.toLatin1();
const char *c_str2 = ba.data();
printf("str2: %s", c_str2);
return app.exec();
}

not able to return QString from c++ function to PERL function by using SWIG

I have c++ code (Includes Qt also), i want to call those functions by using Perl.
Which we can do by using SWIG, so I have implemented interfaces and did all the stuff need to use them in Perl script.
I have a function in c++ which returns a QString value,
QString get_string()
{
return QString("mystring");
}
I have written one more class which will be used in perl script where i have a function which calls this get_string() function and returns const char*.
const char* get_const_string()
{
QString str = get_string();
**//here I print str and str .toLocal8Bit().constData()
//both are printing the text which i shoud get here**
return str.toLocal8Bit().constData();
//here I have tried diff combinations also, as
// return str.toStdString().c_str();
}
The problem is, in get_const_string() function, I could get the string I wanted, but when I call this function in my perl script, I am getting undefine value i.e null string
.
Any idea, what is the problem here ??
I am using perl5, Qt4.8.4
Thanks in advance.
if you cant use a QString return value, maybe you can use std::string.
if both fail and you do not have limitations, you could do some dirty trick:
QString get_string()
{
static QByteArray arr;
QString str = getString();
arr = str.toLocal8Bit();
return arr.constData();
}
note that the arr variable will not be free'd untill your app is running
edit: found a possible solution to just use std::string ... string arguments are not recognized by SWIG

Using SetWindowText with the combination of two buffers

Alright so I have an edit control and a static text control. When the user clicks a button, I want the program to take the text from the edit control and add it to the text in the static text control and then set that new value as the text in the static control. So I have a function that appends the buffers to one another but my program doesn't seem to be working. This is what I have:
//when button message is recieved:
SendMessage(hwndEditControl, WM_GETTEXT,255,(LPARAM)editbuffer);
GetWindowText(hwndTextControl, (LPWSTR)allText, GetWindowTextLength(hwndTextControl));
allText = appendStrings((char*)editbuffer, (char*)allText);
SetWindowText(hwndTextControl, (LPCWSTR)allText);}
// where appendStrings is defined as:
char* appendStrings (char* buffer1, char* buffer2)
{
std::string string1(buffer1), string2(buffer2);
std::string string3 = string1 + string2;
return (char*)string3.c_str();
}
//and
static char* editbuffer = new char;
static char* allText = new char; //these are defined as so
So anyway, when I push the button, I'm pretty sure that the appendStrings function is working because I think it takes what is in the editbox and adds it to the Text box. The reason I say "i think" though is because the string in the text box is always just jibberish. Its sometimes random symbols or just these "l's" (or what look like "L"s). I think it's a problem with my pointers but I'm not sure. I'm new to this so if there is an easier way, please tell me.
You're returning a pointer to a temporary that's being destroyed before the function returns.
Instead of returning a char *, return a std::string.