Wie caste ich von std::function nach LPVOID und zurück
-
Da geht wohl nur ein
reinterpret_cast<...>
.
-
Eine C API braucht unbedingt Callbacks die als "extern C" definiert wurden. Was auch immer an C++ Konstrukt benutzt wird, normalerweise sind C++ Funktionen nicht "extern C" definiert, und man darf auf gar keinen Fall Exceptions durch den C Callstack hindurch propagieren.
-
@Th69 sagte in Wie caste ich von std::function nach LPVOID und zurück:
Da geht wohl nur ein reinterpret_cast<...>.
ja das hatte ich auch schon probiert. Da komme ich auf das selbe Ergebnis.
const auto* const func = reinterpret_cast<std::function<void(shared_ptr<DmDataService>)>*>(lpvUser);
Exception beim Aufruf der Funktion
(*func)(spds);
-
Bei "geht nicht" dachte ich an einen Compilerfehler.
Was für eine Exception?Kann es sein, daß der Callback erst später aufgerufen wird, also wenn
InstallDataService
schon wieder verlassen wurde (siehst du ja am Stacktrace bzw. wenn du einen Breakpoint nach dem Aufruf setzt)?Dann darfst du natürlich keine lokale Variable als Callback-Parameter übergeben!
Das ist also keine Casting-Problem, sondern ein Speichermanagement-Laufzeitfehler.
-
https://en.cppreference.com/w/cpp/utility/functional/function/target
Bitte nicht mit reinterpret_cast rumschludern.
-
Ja natürlich du hast recht. Die Funktion hatte ich inline definiert:
auto func = [=](shared_ptr<wincc::DmDataService> spds) { std::string payload = reinterpret_cast<char*>(&spds->byData[0]); BufferIncomingMessage(payload, spds); };
heißt ich muss das als Klassenmeber machen?
-
Ähm stehe ich gerade auf dem Schlauch. Ist doch egal wenn die Funktion selber inline ist oder? Nur die verwendeten Variablen müssen halt als Kopie übergeben werden und nicht als Referenz. Aber das habe ich doch mit dem Scope:
[=] gemacht.Ich suche schreib noch die Exception raus.
-
Exception thrown at 0x00000000 in script.exe: 0xC0000005: Access violation executing location 0x00000000.
Die ist nicht gerade viel sagend.
-
Du übergibst doch einen Zeiger auf
func
, also muß dieses Objekt noch existieren, wenn die Callback-Funktion aufgerufen wird (ob als Klassenmember kommt darauf an, wielange dieses Objekt "leben" muß).
-
@Th69 sagte in Wie caste ich von std::function nach LPVOID und zurück:
Du übergibst doch einen Zeiger auf
func
, also muß dieses Objekt noch existieren, wenn die Callback-Funktion aufgerufen wird (ob als Klassenmember kommt darauf an, wielange dieses Objekt "leben" muß).Ja und func ist ein lamda und der ist doch auch solange gültig solange die umschliessende Klasse bestand hat. Oder nicht?
Die Klasse ist auf jeden Fall noch da wenn die Callback ausgeführt wird.
-
@booster sagte in Wie caste ich von std::function nach LPVOID und zurück:
Ja und func ist ein lamda und der ist doch auch solange gültig solange die umschliessende Klasse bestand hat. Oder nicht?
Die Klasse ist auf jeden Fall noch da wenn die Callback ausgeführt wird.Wenn das lambda in einer funktion erstellt wurde, dann ist ein zeiger darauf nur bis zum ende dieser Funktion gültig.
Was funktionieren könnte ist, wenn du den lamba einer std::function zuweist, welche ein Member der Klasse ist und dann einen zeiger auf diese std::function der C-Methode übergibst.
-
Warum eigentlich nicht direkt
this
(oder auch ein Objekt, das darin erstellt wurde) an die Callbackfunktion übergeben und eine Memberfunktion direkt aufrufen?
Und warum der Umweg überDmDataService
(und warumshared_ptr
), wenn dich ohnehin anscheinend nur eine Zeichenkette ausDM_DATA_SERVICE
interessiert?typedef struct { DWORD dwTeleType; char szService[MAX_DM_SERVICE_NAME + 1]; char szSendingApp[MAX_DM_APP_NAME + 1]; DWORD dwSendingMachine; DWORD dwDataSize; BYTE byData[1]; // <- das hier, oder? } DM_DATA_SERVICE;
-
@firefly sagte in Wie caste ich von std::function nach LPVOID und zurück:
Wenn das lambda in einer funktion erstellt wurde, dann ist ein zeiger darauf nur bis zum ende dieser Funktion gültig.
Da würde ich glatt mal das Gegenteil behaupten.
-
@yahendrik sagte in Wie caste ich von std::function nach LPVOID und zurück:
Und warum der Umweg über DmDataService (und warum shared_ptr), wenn dich ohnehin anscheinend nur eine Zeichenkette aus DM_DATA_SERVICE interessiert?
Da kennt jemand die Structur
@yahendrik sagte in Wie caste ich von std::function nach LPVOID und zurück:
warum der Umweg über DmDataService
Deshalb:
https://www.c-plusplus.net/forum/topic/351647/kopieren-eines-arrays-in-einem-struct-hack/8Problem ist dass es zwei unterschiedliche Structuren gibt. Einmal für Ansii und einmal für Unicode.
Je nach WinCC Version. Und dass muss ich nach außen vereinheitlichen. Deshalb der Umweg über meine eigene Struktur DmDataService@yahendrik sagte in Wie caste ich von std::function nach LPVOID und zurück:
wenn dich ohnehin anscheinend nur eine Zeichenkette aus DM_DATA_SERVICE interessiert?
Wer sagt das? Das habe ich nirgends geschrieben.
-
Woran erkenne ich denn ob die std::function noch gültig ist?
-
Dieser Beitrag wurde gelöscht!
-
@booster sagte in Wie caste ich von std::function nach LPVOID und zurück:
@firefly sagte in Wie caste ich von std::function nach LPVOID und zurück:
Wenn das lambda in einer funktion erstellt wurde, dann ist ein zeiger darauf nur bis zum ende dieser Funktion gültig.
Da würde ich glatt mal das Gegenteil behaupten.
Und was ist der Grund? Einfach so das gegenteil zu behaupten ohne erklärung ist schlecht
-
Also so ne richtig schöne Erklärung habe ich nirgends gefunden.
Aber vielleicht gibt der Artikel hier Aufschluss.https://www.c-plusplus.net/forum/topic/294038/lebenszeit-von-lambda-funktionen/7
-
Du übergibst aber per
LPVOID(&func)
die Adresse der lokalen Variablenfunc
als Callback-Parameter (nicht einen [globalen] Funktionszeiger) - in dem anderen Beitrag wird ja jeweils beimv.push_back(f)
eine Kopie desstd::function<...>
-Parameters erzeugt.Daher noch mal meine Frage:
Kann es sein, daß der Callback erst später aufgerufen wird, also wenn
InstallDataService
schon wieder verlassen wurde (siehst du ja am Stacktrace bzw. wenn du einen Breakpoint nach dem Aufruf setzt)?
-
Da haben wirs
Aber anders kann ich das ja gar nicht übergeben. Weil es ja ein Zeiger sein muss. Danke dass muss es sein.
Also muss ich die Funktion doch irgendwie als Klassenmember anlegen.