Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

$nooc

Alter Hase

  • »$nooc« ist der Autor dieses Themas

Beiträge: 873

Wohnort: Österreich / Kärnten

Beruf: Schüler

  • Private Nachricht senden

1

17.01.2008, 08:55

Funktion als Parameter

hi leute

ich hab da ein thread-objekt, dessen Create() funktion eine andere funktion als parameter übernimmt (typ: LPTHREAD_START_ROUTINE).

ich will die Create() funktion in einer anderen klasse (frmServer) aufrufen, und ihr eine funktion von frmServer übergeben.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// -------------------------------------------------------------------

// Name:    frmServer_StartServer()

// Desc:    Starts the winsock server.

// -------------------------------------------------------------------

int frmServer::frmServer_StartServer()
{
    // [...]


    if(pServerThread->Create(NULL, 0, &frmServer::frmServer_ServerThreadProc, NULL, 0) != THREAD_CREATING_ERROR)
        return THREAD_CREATING_ERROR;

    // [...]


    return SRV_OK;
} // frmServer_StartServer()






// -------------------------------------------------------------------

// Name:    frmServer_ServerThreadProc()

// Desc:    Thread procedure for the winsock server.

// -------------------------------------------------------------------

DWORD WINAPI frmServer::frmServer_ServerThreadProc (LPVOID lpPAram)
{
    int i = GetCurrentThreadId();
        return i;
} // frmServer_ServerThreadProc()


der compiler meckert aber..

egal wie ich die funktion übergebe..

es geht nicht mit:

frmServer_ServerThreadProc
&frmServer::frmServer_ThreadProc

usw.

wie kann ich die memberfunktion der Create() funktion übergeben?
Am Anfang der Weisheit steht die eigene Erkenntnis, dass man selbst nichts weiß! - Sokrates

rewb0rn

Supermoderator

Beiträge: 2 773

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

2

17.01.2008, 09:01

es ist ein unterschied, ob du eine klassenmethode oder eine funktion übergibst. im schlechtesten fall musst du dir eine kapselungsfunktion schreiben, die die methode deines objektes ausführst. wenn du glück hast gibts für create auch eine variante für klassenmethoden, da musst du mal gucken. in dem fall musst du aber ein objekt mit übergeben, von dem die methode dann aufgerufen wird, weil nur frmServer::frmServer_ThreadProc dem compiler nicht sagt auf welche instanz sich das bezieht.

$nooc

Alter Hase

  • »$nooc« ist der Autor dieses Themas

Beiträge: 873

Wohnort: Österreich / Kärnten

Beruf: Schüler

  • Private Nachricht senden

3

17.01.2008, 09:06

Zitat von »"rewb0rn"«

es ist ein unterschied, ob du eine klassenmethode oder eine funktion übergibst. im schlechtesten fall musst du dir eine kapselungsfunktion schreiben, die die methode deines objektes ausführst. wenn du glück hast gibts für create auch eine variante für klassenmethoden, da musst du mal gucken. in dem fall musst du aber ein objekt mit übergeben, von dem die methode dann aufgerufen wird, weil nur frmServer::frmServer_ThreadProc dem compiler nicht sagt auf welche instanz sich das bezieht.


wie würde eine solche kapselungsfunktion aussehen
die Create() funktion ist von mir, ich kann sie jedezeit verändern ^^
korrigiere mich wenn ich falsch liege, aber könnte ich die Create() so umschreiben dass sie ein objekt erwartet, und dann einfach einen this-zeiger übergeben?


Zitat von »"rewb0rn"«


weil nur frmServer::frmServer_ThreadProc dem compiler nicht sagt auf welche instanz sich das bezieht.


warum geht das nichtmal mit dem this-zeiger?
Am Anfang der Weisheit steht die eigene Erkenntnis, dass man selbst nichts weiß! - Sokrates

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

4

17.01.2008, 10:07

Du hast folgende Möglichkeiten:

o Mach die Methode statisch
o Übergib ein entsprechendes Objekt + dem Funktionszeiger
o Übergib nur ein Objekt (dann ist die Methode halt nicht variabel austauschbar)
o Übergib eine Funktion
o Übergib ein Funktionsobjekt
o Übergib ein Funktor der Methoden + Objekte halten kann

Uswusf... Jetzt musst du nur noch auswählen! :)
@D13_Dreinig

rewb0rn

Supermoderator

Beiträge: 2 773

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

5

17.01.2008, 10:08

ja das geht mit dem this zeiger, hab ich was anderes behauptet? :)

ich kann dir leider keine genaue vorlage geben wie das aussehen muss, da ich gerade nicht zuhause bin um es nachzugucken, aber irgendwie so:

C-/C++-Quelltext

1
2
template<class T>
deinefunktion(T::MemberFunction* (DWORD)(LPVOID), T* Object);


Aufrufen kannst du sie dann so:

C-/C++-Quelltext

1
deinefunktion(&frmServer::frmServer_ThreadProc, this)


Wie gesagt kann gut sein, dass das so nicht ganz korrekt ist, habe das nicht 100%ig im Kopf.

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

6

17.01.2008, 10:17

Ja, fast richtig! :) So siehts genau aus:

C-/C++-Quelltext

1
2
3
4
5
template< typename T >
void test( DWORD ( T::*FunPtr )( LPVOID ), T* instance )
{
    (instance->*FunPtr)(0);
}


Oder per Parameterbinding:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
template<typename T >
void test( std::binder1st<T> fun )
{
    fun(0);
}

// ...


foo bar;
test( std::bind1st( std::mem_fun( &foo::bar ), &bar ) );


Oder per Funktionsobjekt:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
template< typename T >
struct funobj
{
    typedef DWORD ( T::*FunPtr_t )( LPVOID );

    funobj( FunPtr_t fun )
        : ptr( new T() ), fun_( fun )
    {}

    DWORD operator()( LPVOID p )
    {
        return ( *ptr.*fun_ )(p);
    }

private:
    std::auto_ptr<T> ptr;
    FunPtr_t fun_;
};

template< typename T >
void test( funobj<T>& fun )
{
    fun(0);
}

// ...


funobj<foo> obj(&foo::bar);
test( obj );
@D13_Dreinig

$nooc

Alter Hase

  • »$nooc« ist der Autor dieses Themas

Beiträge: 873

Wohnort: Österreich / Kärnten

Beruf: Schüler

  • Private Nachricht senden

7

17.01.2008, 17:18

danke :D

ich werd mir das sobald ich kann ansehn und ausprobieren! :)
Am Anfang der Weisheit steht die eigene Erkenntnis, dass man selbst nichts weiß! - Sokrates

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

8

17.01.2008, 17:42

David hat es schon genannt. Daher hier noch eine Version mit statischer Methode:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
class BasicServer : public Netzwerk
{   
#ifdef _WIN32
    HANDLE ThreadID1, ThreadID2;
#else
    pthread_t thread1, thread2;
#endif
    static DWORD WINAPI empfangenClients(LPVOID);
    static DWORD WINAPI empfangenServer(LPVOID);
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

$nooc

Alter Hase

  • »$nooc« ist der Autor dieses Themas

Beiträge: 873

Wohnort: Österreich / Kärnten

Beruf: Schüler

  • Private Nachricht senden

9

17.01.2008, 17:51

bei mir gibts umsetzungsschwierigkeiten.. sry, sowas hab ich noch nie geschrieben ^^

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// -------------------------------------------------------------------

// Name:    Test()

// Desc:    Creates a new thread.

// -------------------------------------------------------------------

template<typename T>
int Thread::Test(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, DWORD (T::*ThreadProc)(LPVOID), T* instance, LPVOID lpParameter, DWORD dwCreationFlags)
{
    return THREAD_OK;
}

// aufruf:


if(pServerThread->Test(NULL, 0, &frmServer::frmServer_ServerThreadProc, this, NULL, 0) == THREAD_CREATING_ERROR)
        return THREAD_CREATING_ERROR;


da meint mein compiler:

Zitat


error C2784: "int Thread::Test(LPSECURITY_ATTRIBUTES,SIZE_T,DWORD (__thiscall T::* )(LPVOID),T *,LPVOID,DWORD)": template-Argument für "DWORD (__thiscall T::* )(LPVOID)" konnte nicht von "DWORD (__stdcall frmServer::* )(LPVOID)" hergeleitet werden.



also mal angenommen das klappt, kann ich diesen parameter dann verwenden, um ihn einer funktion zu übergeben die diese funktion dann ebenfalls als parameter übernimmt?
Am Anfang der Weisheit steht die eigene Erkenntnis, dass man selbst nichts weiß! - Sokrates

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

10

17.01.2008, 17:55

Ist deine ThreadProc ein Teil der Klasse? Wenn ja muss du die als static deklarieren(definieren? ach keine Ahnung).
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

Werbeanzeige