Wie caste ich von std::function nach LPVOID und zurück
-
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.
-
@booster sagte in Wie caste ich von std::function nach LPVOID und zurück:
Ja natürlich du hast recht. Die Funktion hatte ich inline definiert:
auto func = [=](shared_ptr<wincc::DmDataService> spds)
Wie schwer ist es zu verstehen, dass C Callbacks unbedingt auch als
extern C
definiert sein müssen? Wenn Du Glück hast, hat die member functionwincc::DmDataService
gerade zufällig die passende C Aufrufkonvention, falls Du siestatic
definiert hast. Aber das ist nirgends in der ISO Norm garantiert. Man übergibt auch keinen shared_ptr auch was auch immer sondern immer einen rohen C Zeiger!
-
@john-0 sagte in Wie caste ich von std::function nach LPVOID und zurück:
Wie schwer ist es zu verstehen, dass C Callbacks unbedingt auch als extern C
Hallo John
Wo muss das als extern C definiert sein?
hier?static BOOL OnReceiveData(LPDM_DATA_SERVICE lpds, LPVOID lpvUser);
und wieso darf ich keinen shared_ptr übergeben?
Ich erzeuge mir den Speicher nachher in der callback. Wenn ich nen rohen zeiger verwende und den speicher mit new anlege. Muss ich mich um das löschen kümmern. Und wann mache ich dass. Nachdem der Empfänger die Nachricht verarbeitet hat. Das ist dann nicht schön wenn new und delete in unterschiedlichen Funktionen sind.
-
@john-0: Es geht hier um einen Callback-Parameter, nicht um den Callback-Aufruf selbst (die Funktion
InstallDataService
wird sicherlich alsextern "C"
deklariert sein).
-
@Th69
Ach das meint er. Danke.@Th69 sagte in Wie caste ich von std::function nach LPVOID und zurück:
die Funktion InstallDataService wird sicherlich als "extern "C"`deklariert sein
Sollte sie.
Aber endet nach ein paaar typedefs hier:
BOOL WINAPI DMInstallDataServiceA( LPCSTR lpszService, DM_DATA_SERVICE_PROCA lpfnService, LPVOID lpvUser, LPCMN_ERRORA lpdmError);
Aber darauf habe ich keinen Einfluss.
-
Der ganze Header wird dann per
#ifdef __cplusplus extern "C" { #endif // ... #ifdef __cplusplus } #endif
umschlossen sein.