Hallo
Aus der LVGL Bibliothek habe ich gewisse Meter Beispiele die eine
Funktion verwenden, bei der mein Compiler immer was auszusetzen hat,
siehe Fehler und Funktion unten.
Was ist da falsch? Stimmt etwas mit dem "void*" nicht ?
Danke
Error:
1
src\main.cpp:164:45: error: invalid conversion from ‘void*’ to ‘lv_meter_indicator_t*’ [-fpermissive]
C++ mag keine impliziten Casts von und zu void*, wie das in C üblich
ist. C Code als C++ compiliert halt nicht immer.
Schreib einen expliziten static_cast davor, dann ist auch der
C++-Compiler zufrieden, bzw. überlässt dir die Verantwortung für die
möglichen Probleme.
Oliver
Oliver S. schrieb:> bzw. überlässt dir die Verantwortung für die> möglichen Probleme.
Ob dem TO klar ist was in diesem Fall auf ihn zukommt ... (?)
(denn er sieht ja nicht mal was er aktuell falsch macht)
Danke aber phuu da fehlen mir wohl einiges an Grundlagen... :-(
für
1
lv_anim_set_exec_cb(&a,set_value);
wird scheinbar die oben erwähnte Funktion benötigt. Aber keine Ahnung
wie man das C++ gerecht umschreiben sollte... unten noch der eigentliche
"UI" Code:
Christian schrieb:> lv_meter_set_indicator_end_value(meter, (lv_meter_indicator_t*)indic,> v);
Danke, das funktioniert.
uff basse schrieb:> Ob dem TO klar ist was in diesem Fall auf ihn zukommt ... (?)> (denn er sieht ja nicht mal was er aktuell falsch macht)
Nein ist mir nicht klar, vielleicht ein paar Stichworte?
Das Problem ist halt, dass es sich um ein C-API handelt. Die können
prinzipbedingt nicht sehr typsicher sein und erfordern dann solche
"gefährlichen" casts. Vermutlich muss es genau so sein, aber man müsste
sich das API genau ansehen um es zu prüfen. Ein gut durchdachtes C++-API
würde solche Dinge unnötig machen, aber den Luxus haben wir hier wohl
nicht.
Moin,
Wenn du nicht im code selber 'rumcasten willst: haste mal gemacht, was
der Compiler bei der Fehlermeldung schon vorgeschlagen hat:
Mal mit "-fpermissive" als Option zu compilieren?
Gruss
WK
Programmierer schrieb:> Das Problem ist halt, dass es sich um ein C-API handelt.
Die gezeigte Funktion könnte sehr wohl Teil eines C++ API sein. Auch da
gibt es freestanding Funktionen (im Gegensatz zu Methoden).
Der Fehler ist die Verwendung des void*. Es müßte aber ein Pointer auf
ein Objekt vom Typ lv_meter_indicator_t sein. Oder - wenn es
universeller sein soll - auf ein Objekt einer Basisklasse (gerne rein
virtuell) die die erforderlichen Methoden definiert. Offensichtlich ist
beim API ein wenig (haha) geschlampt worden.
@TE: der cast maskiert dein Problem nur. Der verhindert nicht, daß
jemand die Funktion so aufruft:
Axel S. schrieb:> Die gezeigte Funktion könnte sehr wohl Teil eines C++ API sein. Auch da> gibt es freestanding Funktionen (im Gegensatz zu Methoden).>> Der Fehler ist die Verwendung des void*.
Es ist ein Callback, und mangels templates muss man in C Callbacks halt
mit "void*" verwenden für user_data-Parameter. In C++ könnte man den
Callback als template-"Funktional" übergeben und halt direkt den
richtigen Typ reinsetzen, oder ein Lambda mit Closure und/oder
std::function, oder ganz klassisch Strategy Pattern. Klar KANN man das
in C++ genau so machen wie in C, aber dann verschenkt man Möglichkeiten
und Sicherheit.
Programmierer schrieb:> Klar KANN man das> in C++ genau so machen wie in C, aber dann verschenkt man Möglichkeiten> und Sicherheit.
Der Weg in die Hölle ist mit expliziten Konvertierungen gepflastert.
EAF schrieb:> Der Weg in die Hölle ist mit expliziten Konvertierungen gepflastert.
So ist es, und deswegen schreibt man sie auch aus (static_cast,
reinterpret_cast, dynamic_cast, const_cast) statt die Klammer-Syntax von
C zu verwenden, damit sie hervorstechen und man sofort sieht, wo der
Fehler sitzt!
Programmierer schrieb:> EAF schrieb:>> Der Weg in die Hölle ist mit expliziten Konvertierungen gepflastert.>> So ist es, und deswegen schreibt man sie auch aus (static_cast,> reinterpret_cast, dynamic_cast, const_cast) statt die Klammer-Syntax von> C zu verwenden, damit sie hervorstechen und man sofort sieht, wo der> Fehler sitzt!
Nicht nur deshalb, sondern auch, weil sie spezifischer sind und nicht
einfach mit der Holzhammer-Methode versuchen, alles zu tun, was
irgendwie geht, um vom Quell- zum Zieltyp zu kommen.
Das eigentliche Problem ist hier, dass wir es mit void Zeigern zu tun
haben.
Was wohl der C API geschuldet ist. Die genaue Cast Sorte spielt da
meines Erachtens nach nur eine untergeordnete Rolle. Es ist der Zwang
zum Cast, welcher (mir) hier deplatziert erscheint.
Offensichtlich ein notwendiger Kompromiss, wenn man die Library(?)
unverändert weiter verwenden will.
In der C++ Welt sind void* ehr verpönt. Von allen Zeigern, sind die
void* die kritischsten. Denn sind sie doch das recht genaue Gegenteil
von "Typesicher", und "Typesicherheit" steht recht weit oben auf der C++
Featureliste.
Man könnte evt. einen C++ OOP Wrapper drum rum stricken. Wird aber wohl
eher nicht schön, wenn die Basis nicht von vornherein auf OOP
ausgerichtet ist.
Programmierer schrieb:> C++-typischer und etwas sauberer wäre:> static void set_value( void* indic, int32_t v)> {>> lv_meter_set_indicator_end_value(meter,> static_cast<lv_meter_indicator_t*> (indic), v);> }
Nicht eher so:
EAF schrieb:> Nicht eher so:
Nein, denn dann würde hier ein Fehler auftauchen:
epikao schrieb:> lv_anim_set_exec_cb(&a, set_value);
Und den Funktionspointer will/darf man nicht casten!
lvgl ist sehr sauber strukturiert in C gebaut, das meter widget und
andere haben da schon typisierte Funktionen.
Programmierer schrieb:>> lv_anim_set_exec_cb(&a, set_value);
genau das ist der Punkt, das ist eine generische Animationsfunktion und
die kann dann nur den void* als Adresse haben. Die ist üblicherweise nur
für
Demofunktionen, wenn man da casten muss, dann würde mich das nicht
stören. Gut ist ja das C++ erstmal meckert und den cast erzwingt.
lvgl wird auch plain C bleiben, es gibt generierte Wrapper für
Micropython und ein C++ Interface würde auch so erstellt, das wurde in
lvgl issues schon mehrfach diskutiert. lvgl zu modifizieren ist keine
gute Idee, damit hängt man sich von der (stürmischen) Weiterentwicklung
ab, da ist ein kleiner cast die kleinere Kröte.
Die Beispiele meckern nicht weil da alles C ist, man kann die anim
Funktion auch aus dem main.cpp rausnehmen und in einer C unit lassen.