Callback Funktion programmieren

chefsalat-

Mitglied
Hallo zusammen,
folgendes Szenario:
In einem Dialogfenster sollen beim Initialisieren verschiedene Variablen an einer SPS zum ereignisgesteuerten Lesen angemeldet werden.
Das ganze läuft über Callback-Funktionen. (auf der Konsole gehts ohne Probleme)
Jedes mal, wenn die Variable sich an der SPS geändert hat, soll sie im Dialogfenster aktualisiert werden.

Das Anmelden der Variable an der SPS geht folgendermaßen:
C++:
// Übertragen der SPS-Variablen beginnen 
nErr = AdsSyncAddDeviceNotificationReq(pAddr, ADSIGRP_SYM_VALBYHND, ulHdlVar, &adsNotificationAttrib, Callback, hUser, &hNotification);
Callback ist die Funktion, die aufgerufen werden soll, wenn sich eine Variable verändert hat. Ich werde für jede Variable eine eigene Funktion machen müssen. Aber hier der Übersichtlichkeit halber nur mal für eine Variable.


---------------------------------------------------------------------------------------------------------------

Jetzt mein Problem:
Wenn ich die Callback-Funktionen zu Member-Funktionen des Dialogfensters mache, bekomme ich folgenden Fehler:
C++:
error C2664: 'AdsSyncAddDeviceNotificationReq' : Konvertierung des Parameters 5 von 'void (AmsAddr *,AdsNotificationHeader *,unsigned long)' in 'void (__cdecl *)(AmsAddr *,AdsNotificationHeader *,unsigned long)' nicht moeglich
Keine Funktion mit diesem Namen im Gueltigkeitsbereich stimmt mit dem Zieltyp ueberein
So bekomme ich aber dann Zugriff auf die Edit-Felder, in denen die Variablen aktualisiert werden sollen.

Die entsprechende Header-Datei des Dialogfensters:
C++:
class CTestDlg : public CDialog
{
// Konstruktion
public:
	CTestDlg(CWnd* pParent = NULL);	// Standard-Konstruktor
	void Callback(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser);
	...
}

Und die cpp-Datei des Dialogfensters:
C++:
// Callback-Funktion
void CTestDlg::Callback(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser) {
	m_edit_lichtschranke.SetWindowText("test");
}


---------------------------------------------------------------------------------------------------------------


Mache ich die Callback-Funktionen nicht zu Member-Funktionen des Dialogfensters, habe ich keinen Zugriff auf die Edit-Felder und bekomme diese Fehlermeldung:
C++:
error C2065: 'm_edit_lichtschranke' : nichtdeklarierter Bezeichner
error C2228: Der linke Teil von '.SetWindowTextA' muss eine Klasse/Struktur/Union sein

Die Header-Datei des Dialogfensters:
C++:
void Callback(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser);

class CTestDlg : public CDialog
{
// Konstruktion
public:
	CTestDlg(CWnd* pParent = NULL);	// Standard-Konstruktor
	...
}

Die cpp-Datei - also das Dialogfenster:
C++:
// Callback-Funktion
void Callback(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser) {
	m_edit_lichtschranke.SetWindowText("test");
}




Der Übersichtlichkeit halber habe ich nur "test" in das Edit-Feld geschrieben.

Zum Schluss noch mein System:
- MS Visual C++ 6.0
- Win XP
- Multithreaded

Kann mir bitte jemand helfen, wie ich zu einem Ergebnis komme, bzw. wo ich einen Fehler gemacht habe?

Danke schon mal im Vorraus.
Gruß chefsalat-
 
Ja, der Nachteil, dass man die Klassen in C++ reingepfuscht hat. Member-Funktionen haben einen impliziten Parameter (this), der einen Pointer auf die aktuelle Instanz hält.

Es gibt da verschiedene Möglichkeiten, eine der einfachen:


A) die Callback-Member-Funktionen statisch machen
B) eine statische Member-Variable vom Typ CTestDlg* (m_pDialog) als Member von CTestDlg
C) im Constructor von CTestDlg setzt du m_pDialog auf this
D) in den statischen Funktionen kannst du jetzt per m_pDialog-> auf die Edits zugreifen
 
Danke für deine Anleitung, Endurion. :)
Habs mal eben ausprobiert, bin aber noch nicht arg weiter gekommen.
So siehts bis jetzt aus:

testDlg.h
C++:
protected:
	static void Callback(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser);
	static CTestDlg* m_pDialog;

testDlg.cpp
C++:
CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CTestDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CTestDlg)
	//}}AFX_DATA_INIT
	// Beachten Sie, dass LoadIcon unter Win32 keinen nachfolgenden DestroyIcon-Aufruf benötigt
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_pDialog = this;
}

...

// Callback-Funktion
void CTestDlg::Callback(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser) {
	m_pDialog->m_edit_lichtschranke.SetWindowText("test");
}

Soweit hab ich deine Anweisungen befolgt und hoffentlich alles richtig gemacht, oder

Jetzt bekomm ich aber 2 Fehlermeldungen mit denen ich nichts anfangen kann:
C++:
testDlg.obj : error LNK2001: Nichtaufgeloestes externes Symbol "protected: static class CTestDlg * CTestDlg::m_pDialog" (?m_pDialog@CTestDlg@@1PAV1@A)
Debug/test.exe : fatal error LNK1120: 1 unaufgeloeste externe Verweise

Wer sieht, wo mein Fehler liegt

Gruß chefsalat-
 
Hallo chefsalat,

Könnte es sein, dass deine statische Variable
in der .cpp Datei gar nicht definiert ist?


in der .cpp:

CTestDlg* CTestDlg::m_pDialog = NULL;

//wichtig!
//static Variablen müssen extra definiert werden



Gruß
titanic
 
Morgen titanic,

in der .cpp:

CTestDlg* CTestDlg::m_pDialog = NULL;
ähm :confused: Wo soll das in die cpp rein?
In den Konstruktor von CTestDlg? Ne, denke ich nicht. Da bringt mir eine Deklaration ja nix.



Also in der .h hab ich jetzt mal:
C++:
protected:
	static void Callback(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser);
	static CTestDlg* m_pDialog;

Und in der .cpp siehts so aus:
C++:
CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CTestDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CTestDlg)
	//}}AFX_DATA_INIT
	// Beachten Sie, dass LoadIcon unter Win32 keinen nachfolgenden DestroyIcon-Aufruf benötigt
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	CTestDlg::m_pDialog = this; 
	
}
...
// Callback-Funktion
void CTestDlg::Callback(AmsAddr* pAddr, AdsNotificationHeader* pNotification, ULONG hUser) {
	m_pDialog->m_edit_lichtschranke.SetWindowText("test");
}

Trotzdem kommt noch die Fehlermeldung:
C++:
testDlg.obj : error LNK2001: Nichtaufgeloestes externes Symbol "protected: static class CTestDlg * CTestDlg::m_pDialog" (?m_pDialog@CTestDlg@@1PAV1@A)
Debug/test.exe : fatal error LNK1120: 1 unaufgeloeste externe Verweise
 
Ahhhh, jetzt hab ichs...... *FREU*

C++:
CTestDlg* CTestDlg::m_pDialog = NULL;


CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CTestDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CTestDlg)
	//}}AFX_DATA_INIT
	// Beachten Sie, dass LoadIcon unter Win32 keinen nachfolgenden DestroyIcon-Aufruf benötigt
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	CTestDlg::m_pDialog = this; 
	
}

So tut's.

DANKE!!
 

Neue Beiträge

Zurück