Hallo! Folgendes Problem: Ich versuche ein DLL zu schreiben, dessen Funktionen aus VC++ und VB aufgerufen werden und die eine Funktion des aufrufenden Programmes aufrufen kann. Dabei tritt das Problem auf, dass ich aus der DLL eine Methode einer Klasse im Hauptprogramm aufrufen muss. Ich hab als Beispiel folgende Klasse geschrieben: HEADER class CCaller { typedef void (*CALL_FUNC)(char para); public: void call_function(void); void set_function(CALL_FUNC func); CCaller(); virtual ~CCaller(); private: CALL_FUNC m_function_to_call; }; BODY CCaller::CCaller() { } CCaller::~CCaller() { } void CCaller::set_function(CALL_FUNC func) { this->m_function_to_call = func; } void CCaller::call_function() { this->m_function_to_call(10); } was in C super funktioniert. Jetzt binde ich das ganze in C++ folgendermaßen ein wobei m_caller vom Typ CCaller ist. void CMein_problem_mfcDlg::OnOK() { // TODO: Zusätzliche Prüfung hier einfügen this->m_caller.set_function(&CMein_problem_mfcDlg::call_me); this->m_caller.set_function(call_me); this->m_caller.call_function(); CDialog::OnOK(); } void CMein_problem_mfcDlg::call_me(char param) { char temp[10]; this->MessageBox(itoa(param,temp,10)); } Für die beiden set_function Zeilen bekomme ich Konvertierungsfehler error C2664. Ich hab schon einige Seiten im Internet durchforstet und habe nur Lösungsmöglichkeiten erspäht, die sich auf Zeiger innerhalb einer Klasse, aber nicht über Klassen hinweg erstrecken. Ähnliche Infos sind auch im MSDN Als Anhang hab ich das VC Projekt hinzugefügt. Schonmal Danke für eure Mühen.
Um Memberfunktionen einer Klasse von anderer Stelle per Pointer aufzurufen, müssen diese Memberfunktionen static deklariert sein; beim Aufruf über einen Pointer fehlt nämlich der auf ein Objekt der Klasse verweisende this-Pointer. In Deinem Fall mag es außerdem hilfreich sein, die Zeile mit dem typedef aus der Klassendeklaration hinauszuverlagern. Ansonsten: Poste bitte die vollständigen Fehlermeldungen des Compilers, nicht jeder kennt die Fehlernummern oder hat Lust, nachzusehen, was exakt die bedeuten mögen.
Danke für deine Antwort. Mein grundsätzliches Problem ist, wie ich aus C dem C++ Programm verstänlich machen kann, dass was passiert ist. Eine static deklarierte Funktion kann ja leider wieder nicht auf die Instanz der Klasse zugreifen und wie in meinem Beispiel z.B. eine Messagebox öffnen. Hättest du da nen Tip für mich? Hier noch die Fehlermeldungen: C:\Programme\Microsoft Visual Studio\MyProjects\mein_problem_mfc\mein_problem_mfcDlg.cpp(175) : error C2664: 'set_function' : Konvertierung des Parameters 1 von 'void (__thiscall CMein_problem_mfcDlg::*)(char)' in 'void (__cdecl *)(char)' nicht moeg lich Es gibt keinen Kontext, in dem diese Konvertierung moeglich ist C:\Programme\Microsoft Visual Studio\MyProjects\mein_problem_mfc\mein_problem_mfcDlg.cpp(176) : error C2664: 'set_function' : Konvertierung des Parameters 1 von 'void (char)' in 'void (__cdecl *)(char)' nicht moeglich Keine Funktion mit diesem Namen im Gueltigkeitsbereich stimmt mit dem Zieltyp ueberein
deklariere eine static Funktion und übergib ihr den this zeiger der Instanz des Objectes dann kannst du innerhalb der Funktion drauf zugreifen. Wenn du das Programmübergreifend machen willst also c-dll mit Visualbasicclient dafür gibt es COM schau mal nach COM ATL Programmierung. die Callbackroutinen kanns du dan in VB als Eventroutinen deklarieren und du kannst auch komplette Objekte übergeben.
Der erste Satz von Wolfram bringt es auf den Punkt. Aus diesem Grunde bieten viele Windows-Funktionen, denen Callbackfunktionspointer zu übergeben sind, auch die Möglichkeit, einen benutzerdefinierten Wert zu übergeben, der dann bei Aufruf der Callbackfunktion mitgeliefert wird. Alternativ ließe sich, sofern vom betreffenden Objekt nur eine Instanz existiert, ein Pointer darauf als globale Variable ablegen und in der statischen Memberfunktion als this-Äquivalent verwenden.
Danke Wolfram! Das Problem ist, dass die DLL von Leuten benutzt werden soll, die nicht allzuviel Ahnung von VB Programmierung haben. In VB ist es ja mit dem Adress of Operator relativ leicht ner dll eine Callback Funktion zu übergeben. Wenn ich dass dann noch in ner .bas Datei in ner "Init" Funktion kapsel müssten man damit zurecht kommen. Das Verwenden der C++ Callback Geschichte soll für mich sein. Mit der statischen Methode ist das Ganze irgendwie "Vom Zeh durch die Hand um den Hals zur Brust". Hätte gedacht da gibt es was eleganteres. Hier also mal der C++ Ansatz mit "static" class CToCall { public: void ToCallInstance(); static void ToCallStatic(char in); CToCall(); virtual ~CToCall(); static CToCall *mythis; private: }; CToCall *CToCall::mythis = 0; CToCall::CToCall() { this->mythis = this; } CToCall::~CToCall() { } void CToCall::ToCallStatic(char in) { mythis->ToCallInstance(); } void CToCall::ToCallInstance() { //Do Something } Und dann folgendes, wo mans braucht CCaller caller; CToCall to_call; caller.set_function(&CToCall::ToCallStatic); caller.call_function();[/cpp] das kann man natürlich abwandeln, indem man CToCall an die eigentliche Klasse vererbt, die den Event braucht und ToCallInstance oder ToCallStatic überschreibt usw. Für weitere Tipps bin ich natürlich dankbar!
Damit man das verstehen kann, wirst Du ein wenig mehr ausholen müssen. Was für eine Aufgabe soll die DLL haben; was für ein Aufrufinterface soll diese DLL bieten? Was hat das ganze mit VB zu tun?
Der Code sollte nur als Beispiel Dienen... Die ToCall Klasse soll die C++-Klasse im Hauptprogramm "simulieren". Die Caller Klasse liegt dann in der DLL. Wobei die Caller Klasse auch komplett in C geschrieben sein könnte. Ziel des ganzen Unterfangens ist eine DLL für die Kommunikation mit Geräten, die an die Serielle Schnittstelle angeschlossen sind. Die Kommunikation läuft in Rahmen ab. Die DLL packt nun Daten, die sie über z.B. über sende_daten(Daten data) erhält. Dann soll sie natürlich auch dem Hauptprogramm melden wann Daten vom Gerät kommen. Dazu gibt das Hauptprogramm eine aufzurufende Funktion mit z.B. set_Callback_Function(CALLBACKFUNCTION func) an die DLL. Diese Funktion wird dann von der DLL mit Übergabeparametern in welchen die empfangen Daten liegen aufgerufen.
genau sowas hab ich vor einer Woche geschrieben am Seriellen Port haengt ein Gerät was ein Protokoll spricht die DLL ist zur Kapselung des Protokolls Ich habe es als COM-DLL gelöst 1. für den Anwender ist es einfacher BSP im VB6-Client dim withevents myObj as (Object in COM DLL) set myObj=new .... myObj.Methode1 .. ab da kann man dann eine Eventroutine deklarieren 2. Grund .NET unterstützt derzeit KEINE Callbackroutinen aus normalen DLL's laut MSDN (.Net Kapselt die DLL oder COM-DLL mit einer Proxy DLL) also wenn ein neueres Visual studio zum Einsatz kommt wirds aussr in C problematisch Im Netz findet man genügend Bsp. für einfache COM Server Allerdings lohnt es sich dann darueber nachzudenken ob man nicht die übertragenen Werte in Properties kapselt.Beispielsweise ADC Werte bei Zugriff darauf wird ein Lesebefehl ausgelöst... Ich hatte dein Problem auch da ich einen Thread der das Gerät ständig abfragte, brauchte. Und der geht nur als static. Sonst kann man ein CreateThread vergessen.
mhhh.. das mit .net ist natürlich wirklich schade :( ich habs jetzt erstmal mit der static Varianten gelöst und das Polling der Schnittstelle macht ein eigener Thread, wo wie du schon gesagt hast das gleiche Probelm auftritt... aber auch mit der static methode gelöst.
Es gibt durchaus pointer auf non-static member functions. Nur sehen die ein bischen anders aus: typedef void (CCaller::*CALL_FUNC)(char para); Der Funktion set_function kann nun eine beliebige void(char) member function von CCaller oder einer davon abgeleiteten Klasse übergeben werden. Ist also CMein_problem_mfcDlg von CCaller abgeleitet, dann sollte der Rest wie oben funktionieren. Intern werden solche pointer anders dargestellt also normale function pointer, sie brauchen deutlich mehr Platz.
Fehlt natürlich noch etwas. Grad der Aufruf sieht anders aus, in expliziter Form: void CCaller::call_function() { (this->*(this->m_function_to_call))(10); } Wobei sich sicher das eine oder andere this einsparen lässt.
> Wobei sich sicher das eine oder andere this einsparen lässt.
Das zweite this kann man sich sparen, ebenso wie die Klammern um
m_function_to_call.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.