Klasse mit CALLVACK Funktion



  • Guten MOrgen. Ich habe folgendes Problem :
    Ich habe eine Klasse von der ich eine Instanz erstelle. Ich möchte von einer anderen KLasse in bestimmte Zeitabständen zyklisch eine Funktion aufrufen. Das klappt auch schon ganz gut, ich habe diese Funktione als CALLBACK Funktion dekjlariert. Nun soll diese CALLBACK Funktion allerdings eine weitere Funktion der Klasse aufrufen. UNd gibt es bereits die ersten Probleme :

    error C2352: 'UpdateAgent::ScanFolder' : illegal call of non-static member function
            f:\programmierung\filemanager\updateagent.h(27) : see declaration of 'ScanFolder'
    

    Ich habe die Funktion ScanFolder als static deklariert und der Fehler ist verschwunden. Jedoch soll nun in der ScanFUnktion auf einen Zeiger zugegriffen werden, und da bekomme ich einen LInker Error :

    unresolved external symbol "private: static class DatabaseAgent * UpdateAgent::pDatabasAgent" (?pDatabasAgent@UpdateAgent@@0PAVDatabaseAgent@@A)
    Debug/FileManager.exe : fatal error LNK1120: 1 unresolved externals
    

    So und hier mal der COde der kLAsse:

    class UpdateAgent
    {
    public:
    	UpdateAgent(DatabaseAgent *databasagent);
    	~UpdateAgent();
    
    	static void CALLBACK TestFunktion(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2);
    
    private:
    
    	static void ScanFolder(string folder);
    	static void WriteFileInformation(string filename);
    	static string ConvertDwordToString(DWORD number);
    	static string ConvertBoolToString(bool value);
    
    	static DatabaseAgent *pDatabasAgent;
    };
    
    // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
    
    #endif
    

    un die implemetiereung

    void UpdateAgent::ScanFolder(string folder)
    {
    	WIN32_FIND_DATA FindFileData;
    	HANDLE hFind; 
    
    	// Erweitere den OrdnerNamen => Suchmaske üfr alle Dateien
    	string SearchFolder = folder + "\\*.*";
    
    	// Suche die erste Datei.
    	hFind = FindFirstFile(SearchFolder.c_str(),&FindFileData);
    
    	// Prüfe ob der DateiHandle gültig ist
    	if (hFind != INVALID_HANDLE_VALUE)
    	{
    		do
    		{
    			// Wenn die Datei ein Ordner ist.
    			if ( FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY  && lstrcmp (FindFileData.cFileName, "..") != 0 && lstrcmp(FindFileData.cFileName,".") != 0 )
    				 ScanFolder( folder + "\\" + FindFileData.cFileName );
    
    			// Wenn die Datei nicht ein Ordner ist.
    			if ( ! ( FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
    			{
    
    				WriteFileInformation(folder + "\\" + FindFileData.cFileName);	
    			}
    
    		}	while (FindNextFile(hFind,&FindFileData));			
    	}
    	else
    	{
    
    	}
    
    	FindClose(hFind); 
    }
    
    // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
    
    void UpdateAgent::WriteFileInformation(string filename)
    {
    		// Lese alle Datei - Informationen zur Datei
    
    	WIN32_FIND_DATA FindFileData;
    	HANDLE hFind; 
    
    	// Sucht nach der Datei
    	hFind = FindFirstFile(filename.c_str(),&FindFileData);
    
    	// Prüfe ob der DateiHandle gültig ist
    	if (hFind != INVALID_HANDLE_VALUE)
    	{
    		// Entfernt alle überflüssigen Zeichen aus dem Dateinamen.
    		//file = RemoveCharacterFromString("'",file);
    
    		// Erzeugt das Datum 
    		SYSTEMTIME  t_Creation, t_LastAccess, t_LastWriteTime;
    
    		FileTimeToSystemTime(&FindFileData.ftCreationTime,&t_Creation);
    		FileTimeToSystemTime(&FindFileData.ftLastAccessTime,&t_LastAccess);
    		FileTimeToSystemTime(&FindFileData.ftLastWriteTime,&t_LastWriteTime);
    
    		// Erzeugt den SQL - String
    		string sql = "INSERT INTO SearchResult (FileName,FileSize,FileType,CreationTime,LastAccessTime, LastWriteTime,FlieAttributeArchiv,FlieAttributeDirectory,FlieAttributeHidden,FlieAttributeReadOnly,FlieAttributeSystem, FileContent) VALUES ";
    		sql += "('";
    		sql += filename;
    		sql += "',";
    		sql += ConvertDwordToString(FindFileData.nFileSizeLow);
    		sql += ",'";
    		sql += filename.substr(filename.find_last_of(".") + 1);
    		sql += "','";
    		sql += ConvertDwordToString(t_Creation.wDay);
    		sql += ".";
    		sql += ConvertDwordToString(t_Creation.wMonth);
    		sql += ".";
    		sql += ConvertDwordToString(t_Creation.wYear);
    		sql += " ";
    		sql += ConvertDwordToString(t_Creation.wHour);
    		sql += ":";
    		sql += ConvertDwordToString(t_Creation.wMinute);
    		sql += ":";
    		sql += ConvertDwordToString(t_Creation.wSecond);
    		sql += "','";
    		sql += ConvertDwordToString(t_LastAccess.wDay);
    		sql += ".";
    		sql += ConvertDwordToString(t_LastAccess.wMonth);
    		sql += ".";
    		sql += ConvertDwordToString(t_LastAccess.wYear);
    		sql += " ";
    		sql += ConvertDwordToString(t_LastAccess.wHour);
    		sql += ":";
    		sql += ConvertDwordToString(t_LastAccess.wMinute);
    		sql += ":";
    		sql += ConvertDwordToString(t_LastAccess.wSecond);
    		sql += "','";
    		sql += ConvertDwordToString(t_LastWriteTime.wDay);
    		sql += ".";
    		sql += ConvertDwordToString(t_LastWriteTime.wMonth);
    		sql += ".";
    		sql += ConvertDwordToString(t_LastWriteTime.wYear);
    		sql += " ";
    		sql += ConvertDwordToString(t_LastWriteTime.wHour);
    		sql += ":";
    		sql += ConvertDwordToString(t_LastWriteTime.wMinute);
    		sql += ":";
    		sql += ConvertDwordToString(t_LastWriteTime.wSecond);
    		sql += "',";
    		sql += ConvertBoolToString(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE);
    		sql += ",";
    		sql += ConvertBoolToString(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
    		sql += ",";
    		sql += ConvertBoolToString(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN);
    		sql += ",";
    		sql += ConvertBoolToString(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY);
    		sql += ",";
    		sql += ConvertBoolToString(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM);
    		sql += ",'";
    
    		pDatabasAgent->ExcecuteSQLCommand(sql);
    
    		FindClose(hFind); 
    	}	
    }
    
    // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
    
    string UpdateAgent::ConvertDwordToString(DWORD number)
    {
    	// Wandelt eine DWORD - Variable in einen String um.
    
    	char buffer[10];
    	return ultoa(number,buffer,10);
    }
    
    // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
    
    string UpdateAgent::ConvertBoolToString(bool value)
    {
    	// Wandelt eine BOOL - Variable in einen String um.
    
    	if (value)
    		return "true";
    	return "false";
    }
    
    // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
    
    void CALLBACK UpdateAgent::TestFunktion(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2)
    {
    	 ScanFolder("D:");
    
    	cout << "Test\n";
    
    }
    
    // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
    

    Kann mir da jemand helfen . Eine erklärung bezüglich der CALLBACk und static funktionen wäre schön. Vielen Dank



  • Das ist eine Falle, in die man durch die strikte Trennung von Deklaration und Definition in C++ tritt.
    Du brauchst einfach noch eine Definition für die static-Variable. In die cpp-Datei folgendes eintragen:

    DatabaseAgent* DatabaseAgent::pDatabasAgent;
    

    Die Callbackfunktion muss statisch sein, weil sie keinen this-Pointer vom Aufrufer erhält.



  • Danke für deine Antwort ich werde es gleich ausprobiere



  • Danke es hat geklappt. Aber warum das habe cih noch nicht verstanden. Ich habe doch im KOnstruktor einen Zeiger auf das DatbasAGent Objekt mitgegeben.



  • Ja, aber beim Augruf einer statischen Methode wird wohl kaum der Konstruktor der Klasse aufgerufen, stimmt's? 😉



  • Nein das stimmt aber so habe ich das auch nicht gemeint. Wenn ich ein Objekt dieser KLasse Erzuege rufe ich doch den Konstrutor auf. Und dem gebe ich einen Zeiger mit. So und nun die Frage warum ich den nicht so einfach verwenden kann ?



  • Du kannst den übergebenen Zeiger benutzen. Du machst aber eine Kopie davon, die du in pDatabasAgent aufbewahren möchtest. Für diese statische Variable muss Speicherplatz zur Verfügung stehen. Die reine Deklaration wie bei nicht-statischen Membern reicht dazu blöderweise nicht, man muss den Compiler explizit anweisen, die Variable zu instanzieren.


Anmelden zum Antworten