*
@booster sagte in Wie caste ich von std::function nach LPVOID und zurück:
Wo muss das als extern C definiert sein?
hier?
Weil C Funktionen und C++ Funktionen eine andere Calling Convention haben, z.B. member functions übergeben immer verdeckt den this parameter, das Exception Handling von C++ spielt da auch eine Rolle. Es wird nur für extern C Funktionen garantiert, dass sie exakt den Calling Conventions von C entsprechen. D.h. macht man eine member function static kann das funktionieren, aber es gibt keine Garantie -> UB. Möglicherweise steht etwas dazu in der Doku. Es gibt keinen Weg eine Member Function extern C zu definieren, also bleibt nur der Weg einer eigenen Funktion. Benutzte deshalb eine simple extern C Wrapper Function, die alle Exceptions abfängt, und dann Deine Member Function aufruft.
Ich kenne die Win API nicht, aber OnReceiveData sieht mir nicht nach einer C++ API aus, so dass wahrscheinlich hier ebenfalls C Konventionen notwendig sein werden. Es sieht mir auch nicht nach einer C++ Wrapper Funktion aus an die man eine C++ Funktion übergeben könnte. Das würde eher eine abgeleitete Klasse oder für den Wrapper ein Template erfordern OnReceiveData hat weder das eine noch das andere im Interface.
und wieso darf ich keinen shared_ptr übergeben?
Pass auf, dass da kein Durcheinander entsteht. Normale Zeiger lassen sich mit einem simplen static_cast konvertieren. Dazu bietet sich der this-Pointer an. In der C Wrapper Funktion castest Du den void* Zeiger auf den Klassentypen Deiner Klasse und rufst die eigene Member Function auf. Die shared_ptr etc. legst Du ganz normal als Member in der Klasse an, da brauchst Du nichts von Hand zu machen.
Nachtrag:
Als Beispiel wie das so aussehen sollte ein kleines rudimentäres Beispiel mit pthreads und passender Callback Funktion. In diesem Beispiel ließe sich das leicht erweitern, in dem man einfach von der Klasse thread ableitet und dann kann man pro Ableitung eine neue Member Function run definieren.
#include <pthread.h>
#include <cstdlib>
#include <iostream>
#include <boost/core/noncopyable.hpp>
class thread_attr : private boost::noncopyable {
pthread_attr_t attr;
public:
thread_attr () {
pthread_attr_init (&attr);
}
~thread_attr() {
pthread_attr_destroy (&attr);
}
pthread_attr_t* get() {
return &attr;
}
};
extern "C" {
void* callback (void* arg) noexcept;
}
class thread : private boost::noncopyable {
thread_attr attr;
pthread_t thr;
public:
virtual void run() {
std::cout << "thread::run" << std::endl;
}
thread () {
pthread_create(&thr,attr.get(),&callback,this);
}
~thread() {
pthread_join(thr,nullptr);
}
};
extern "C" {
void* callback (void* arg) noexcept {
thread* tr = static_cast<thread*>(arg);
try {
tr->run();
}
catch (...) {
std::cerr << "callback exception" << std::endl;
}
return nullptr;
}
}
int main () {
thread t1;
return EXIT_SUCCESS;
}