Funktionszeiger auf eine Methode einer nicht-statischen Klasse? (für PThread) - gelöst



  • Hallo liebe Community,

    leider komme ich trotz dieses Tutorials (http://www.newty.de/fpt/index.html) bis jetzt nicht weiter. Ich bin mir zwar nicht ganz sicher, ob das Thema hierhin oder in den Linuxbereich gehört, aber da es ja eigentlich kein PThreadproblem ist, habe ich es mal in den C++-Bereich gestellt.

    Hier ein Minimalbeispiel für mein Problem:

    /* main.cpp */
    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <sched.h>
    
    using namespace std;
    
    class Klasse {
    public:
    	void* machwasnormales(void* arg) { cout << "normales hallo" << endl; };
    	static void* machwasstatisches(void* arg) { cout << "statisches hallo" << endl; };
    };
    
    int main(int argc, char **argv)
    {
    	pthread_attr_t tattr;
    	pthread_t tid;
    	int ret;
    	pthread_t thread;
    	ret = pthread_attr_init (&tattr);
    	Klasse instanz;
    	int iret = pthread_create(&thread, &tattr, &(Klasse::machwasstatisches), NULL);
    	pthread_join(thread, NULL);
    	return 0;
    }
    
    g++ -pthread main.cpp
    

    So, wie ihr euch ja wahrscheinlich schon denken könnt, würde ich ganz gern das "normale hallo" aus nem Thread heraus zu sehen bekommen.

    Wär super, wenn ihr mir helfen könntet.
    Vielen Dank im Voraus.

    Dobias

    PS: Falls es irgendwie wichtig ist: Ich arbeite unter Ubuntu 9.04 mit g++ 4.3.3.



  • Was genau ist jetzt dein Problem?
    Wir sind hier nicht bei "Rate mal mit Rosenthal"



  • Sorry, wenn ich mich so unverständlich ausgedrückt habe.
    Ich möchte einen Thread starten, der nicht mit Klasse::machwasstatisches läuft, was ja wunderbar funktioniert, sondern einen, der instanz::machwasnormales benutzt.
    Ein einfaches

    int iret = pthread_create(&thread, &tattr, &(instanz.machwasnormales), NULL);
    

    tut es hier natürlich nicht.

    main.cpp: In function ‘int main(int, char**)’:
    main.cpp:24: error: ISO C++ forbids taking the address of a bound member function to form a pointer to member function.  Say ‘&Klasse::machwasnormales’
    main.cpp:24: error: cannot convert ‘void* (Klasse::*)(void*)’ to ‘void* (*)(void*)’ for argument ‘3’ to ‘int pthread_create(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*)’
    

    Schon allein, weil der Funktionsaufruf ja noch den this-Zeiger der Instanz als Parameter mitbekommt.
    Meine Frage ist jetzt: Wie macht ich es richtig?



  • Du musst ganz einfach das Objekt selbst auch noch irgendwie mitliefern.
    Sprich, schlussendlich hast du eine statische Funktion und übergibst das Objekt irgendwie anderst. Vlt. wird ja irgendwas von Haus aus unterstützt (wie z.B zusätzliche Parameter) oder ansonsten musst du da einen Umweg machen, um die Auswahl des Objektes anderst treffen.



  • Ok, vielen Dank. Hab was passendes gefunden.
    http://www.tuxtips.org/?p=5

    #include <iostream>
    #include <string>
    #include <pthread.h>
    
    using namespace std;
    class example
    {
            public:
                    string s;
                    void say_hi() { cout<<"hello "<<s<<endl; }
                    void (example::*func())() { return &example::say_hi; }
                    void get_hi()
                    {
                            void ((example::*foo)()) =  func();
                            (this->*foo)();
                    }
                    static void* thread_maker(void* dat_s);
    };
    
    struct val_st
    {
            example* e;
            void (example::*func)();
    };
    
    void* example::thread_maker(void* dat_s)
    {
            struct val_st* v = static_cast<val_st*>(dat_s);
            example* e = v->e;
            void ((example::*f)()) = v->func;
            (e->*f)();
            return NULL;
    }
    
    int main()
    {
            pthread_t launch_thread;
            example foo;
            example bar;
            val_st v;
            foo.s = "world";
            bar.s = "there";
            foo.get_hi();
            bar.get_hi();
            void ((example::*f)()) =  bar.func();
            (foo.*f)();
            v.e = &foo;
            v.func = foo.func();
            pthread_create(&launch_thread, NULL, &example::thread_maker, static_cast<void*>(&v));
            pthread_join(launch_thread,NULL);
            return 0;
    }
    

Anmelden zum Antworten