Konvertieren Sie den C++-Funktionszeiger in den C-Funktionszeiger

Konvertieren Sie den C++-Funktionszeiger in den C-Funktionszeiger


Ich entwickle eine C++-Anwendung mit einer C-Bibliothek. Ich muss einen Zeiger zur Funktion an die C-Bibliothek senden.


Das ist meine Klasse:


 class MainWindow : public QMainWindow {  
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private:
Ui::MainWindow *ui;
void f(int*);
private slots:
void on_btn_clicked();
};

Dies ist meine on_btn_clicked-Funktion:


void MainWindow::on_btn_clicked()
{
void (MainWindow::* ptfptr) (int*) = &MainWindow::f;
c_library_function(static_cast<void()(int*)>(ptfptr), NULL);
}

Die C-Funktion sollte einen Zeiger auf eine solche Funktion erhalten:void f(int*).
Aber der obige Code funktioniert nicht, ich kann meine f-Member-Funktion nicht in den gewünschten Zeiger umwandeln.


Kann jemand bitte helfen?


Antworten:


Wenn ich mich richtig erinnere, können nur statische Methoden einer Klasse über "normale" C-Zeiger auf Funktionssyntax angesprochen werden. Versuchen Sie also, es statisch zu machen. Der Zeiger auf eine Methode einer Klasse benötigt zusätzliche Informationen, wie das "Objekt" (this), das für eine reine C-Methode keine Bedeutung hat.


Die hier gezeigte FAQ hat eine gute Erklärung und eine mögliche (hässliche) Lösung für Ihr Problem.


Einige Code-Antworten


 class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private:
Ui::MainWindow *ui;
void f(int*);
private slots:
void on_btn_clicked();
};
void MainWindow::on_btn_clicked() {
void (MainWindow::* ptfptr) (int*) = &MainWindow::f;
c_library_function(static_cast<void()(int*)>(ptfptr), NULL);
}
class MyClass {
void non_static_func(/* args */);
public:
static void static_func(MyClass *ptr, /* other args */) {
ptr->non_static_func(/* other args */);
} };
c_library_function(MyClass::static_func, this);
template <typename T>
struct Callback;
template <typename Ret, typename... Params>
struct Callback<Ret(Params...)>
{
template <typename... Args>
static Ret callback(Args... args) { return func(args...);
}
static std::function<Ret(Params...)>
func;
};
// Initialize the static member. template <typename Ret, typename... Params>
std::function<Ret(Params...)>
Callback<Ret(Params...)>::func;
struct Foo {
void print(int* x) { // Some member function.
std::cout <<
*x <<
std::endl;
} };
int main() {
Foo foo;
// Create instance of Foo.
// Store member function and the instance using std::bind.
Callback<void(int*)>::func = std::bind(&Foo::print, foo, std::placeholders::_1);
// Convert callback-function to c-pointer.
void (*c_func)(int*) = static_cast<decltype(c_func)>(Callback<void(int*)>::callback);
// Use in any way you wish.
std::unique_ptr<int>
iptr{new int(5)};
c_func(iptr.get());
}
typedef void (*voidCCallback)();
template<typename T>
voidCCallback makeCCallback(void (T::*method)(),T* r){ Callback<void()>::func = std::bind(method, r);
void (*c_function_pointer)() = static_cast<decltype(c_function_pointer)>(Callback<void()>::callback);
return c_function_pointer;
}
voidCCallback callback = makeCCallback(&Foo::print, this);
plainOldCFunction(callback);
 #include <type_traits>
template<typename T>
struct ActualType {
typedef T type;
};
template<typename T>
struct ActualType<T*>
{
typedef typename ActualType<T>::type type;
};
template<typename T, unsigned int n,typename CallerType>
struct Callback;
template<typename Ret, typename ... Params, unsigned int n,typename CallerType>
struct Callback<Ret(Params...), n,CallerType>
{
typedef Ret (*ret_cb)(Params...);
template<typename ... Args>
static Ret callback(Args ... args) {
func(args...);
}
static ret_cb getCallback(std::function<Ret(Params...)>
fn) {
func = fn;
return static_cast<ret_cb>(Callback<Ret(Params...), n,CallerType>::callback);
}
static std::function<Ret(Params...)>
func;
};
template<typename Ret, typename ... Params, unsigned int n,typename CallerType>
std::function<Ret(Params...)>
Callback<Ret(Params...), n,CallerType>::func;
#define GETCB(ptrtype,callertype) Callback<ActualType<ptrtype>::type,__COUNTER__,callertype>::getCallback
typedef void (cb_type)(uint8_t, uint8_t);
class testfunc { public:
void test(int x) {
std::cout <<
"in testfunc.test " <<x<<
std::endl;
}
void test1(int x) {
std::cout <<
"in testfunc.test1 " <<x<<
std::endl;
} };
cb_type* f = GETCB(cb_type, testfunc)(std::bind(&testfunc::test, tf, std::placeholders::_2));
cb_type* f1 = GETCB(cb_type, testfunc)(
std::bind(&testfunc::test1, tf, std::placeholders::_2));
f(5, 4);
f1(5, 7);
void (*window_callback)(MainWindow*,int*) = std::mem_fn(&MainWindow::on_btn_clicked);
void window_button_click_wrapper(int* arg) {
MainWindow::inst()->on_btn_clicked(arg);
}
class MainWindow;
static MainWindow* instance;
class MainWindow { public: MainWindow() {
instance = this;
registerCallback([](int* arg){instance->...});
} };