[英]Handling of const char* on ESP32
I'm working on making some Spotify API calls on an ESP32.我正在对 ESP32 进行一些 Spotify API 调用。 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.
我对 C++ 还很陌生,虽然我似乎让它按照我想要的方式工作,但我想知道这是否是正确的方法/最佳实践,或者我是否只是幸运。 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.我正在调用 Spotify API,获得 json 响应并使用 ArduinoJson 库对其进行解析。 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.该库将所有键和值作为
const char*
返回。我用来在屏幕上显示它的库也采用const char*
。 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.我在将它转换为字符串之前让它工作,使用 getTitle() function 返回字符串并将其转换回屏幕上显示。 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?这样做可以吗?
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 .这是因为在
getTitle
中,您正在向本地object ( item
) 请求指针 - 但您稍后使用该指针,此时item
object 不再存在。
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".此问题与您使用的确切库无关,您通常可以通过在库文档中搜索“生命周期”或“对象所有权”来找到相关的、更具体的信息。
Make sure that item
(and also DynamicJsonDocument
, because the documentation tells you so,) both still exist when you use the data.确保该
item
(以及DynamicJsonDocument
,因为文档告诉您)在您使用数据时仍然存在。 eg: 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另请参阅: https://arduinojson.org/v6/how-to/reuse-a-json-document/#the-best-way-to-use-arduinojson
You could keep the JSON document "alive" for when the parsed data is needed:您可以在需要解析数据时保持 JSON 文档“活动”:
/* "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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.