c_DLL Wrapper



  • Ich habe so gemacht:

    struct Sensor_Wrapper
    {
    	void *Csensor; // intern ein CSensor* !!!
    }; 
    
    Sensor_Wrapper create_sensor_wrapper()
    {
      Sensor_Wrapper sensor_wrapper;
    
      CSensor* sensor = new CSensor(const CEFI_Out &e); // <-- hier noch passende Parameter angeben
    
      sensor_wrapper.Csensor = static_cast<void *>(sensor);
    
      return sensor_wrapper;
    }
    

    Ist das richtig?



  • Ich habe so gemacht:

    struct Sensor_Wrapper
    {
    	void *Csensor; // intern ein CSensor* !!!
    }; 
    
    Sensor_Wrapper create_sensor_wrapper()
    {
      Sensor_Wrapper sensor_wrapper;
    
      CSensor* sensor = new CSensor(const CSensor &e); // <-- hier noch passende Parameter angeben
    
      sensor_wrapper.Csensor = static_cast<void *>(sensor);
    
      return sensor_wrapper;
    }
    

    Ist das richtig?



  • CSensor* sensor = new CSensor(const CSensor &e); // <-- hier noch passende Parameter angeben
    

    Ist das bitte richtig?



  • Wenn du das in den Klammern noch durch einen sinnvollen Wert ersetzt...



  • hier ist meine Version:

    struct Sensor_Wrapper
    {
    	void *Csensor(const CSensor &e); // intern ein CSensor* !!!
    }; 
    
    Sensor_Wrapper create_sensor_wrapper()
    {
      Sensor_Wrapper sensor_wrapper;
    
      CSensor* sensor = new CSensor(const CSensor &e); // <-- hier noch passende Parameter angeben
    
      sensor_wrapper.Csensor = static_cast<void *>(sensor);
    
      return sensor_wrapper;
    }
    


  • Was soll den bitte der Kopierkonstruktor da? Du sollte ersteinmal ein CSensor-Objekt erstellen (bevor du es kopieren kannst).

    Aus deinem ersten Beitrag heraus wohl diesen Konstruktor aufrufen

    CSensor(CPerson * PPerson);
    

    (woher die Person kommt, mußt du natürlich selber wissen - z.B. als Wrapper-Parameter, welche wiederum mittels einer create_person()-Funktion erstellt wurde etc. pp.)

    Nur noch mal als Nachtrag:

    Dies ist deine Wrapper-Struktur (in C):

    struct Sensor_Wrapper
    {
        void *sensor; // intern ein CSensor* !!!
    };
    

    Genau so und nicht anders!!!

    Der void* ist in C nötig, weil C halt keine Klassen kennt (diese aber dann von deinem C++-Code aus als Klasseninstanz interpretiert (gecastet) werden kann.



  • die Klasse CPerson sieht ao aus:

    class CPerson: public CZeit, public CGeld, public CTier
    {
    	public:
    	typedef enum Produkt{ undef, Spezifikation_A, Spezikatation_B, Spezifikation_C} t_Produkt;
    	typedef enum PassendeZeit { SystemStart, SystemPause} t_PassendeZeit;
    	......
    	CPerson(t_Produkt enProdukt = Spezifikation_A, t_Kombination Kombination = testErfolg, t_AsicType asictype = HLM2012 ): CKombination(Kombination),CAsicSort(asictype)
    	{
    		Produkttype(Spezifikation_A);
    		DefaultValues();
    	}
    	CPerson (const CPerson &e, const CKombination &k, const CAsicSort &a): CCAsicSort(a),CKombination(k) 
    	{
    		.....
    
    	}
    	//Getter
    	....
    	// Setter
    	.....
    };
    

    soll ich auf für die eine struct erzeugen?
    Wie mache ich das denn in C, wenn die Klasse CPerson noch von 3 Klassen erbt?


  • Mod

    class CPerson: public CZeit, public CGeld, public CTier
    

    class Zeit: public Geld hätte ich ja noch verstanden, aber das hier? 😮 Du hast Objektorientierung bei Jürgen Wolf gelernt, oder?

    P.S.: CFindest Cdu Cdas Ceigentlich Clesbar?

    P.P.S.: Da du anscheinend nicht der aufmerksamste Leser bist, noch einmal als Klartext: Du hast derzeit ganz andere Probleme, als einen C-Wrapper um eine C++-Klasse zu schreiben.



  • Das habe ich nicht selber programmieren (leider).
    Ich habe einfach die Suppe übernommen.

    SeppJ schrieb:

    class CPerson: public CZeit, public CGeld, public CTier
    

    class Zeit: public Geld hätte ich ja noch verstanden, aber das hier? 😮 Du hast Objektorientierung bei Jürgen Wolf gelernt, oder?

    P.S.: CFindest Cdu Cdas Ceigentlich Clesbar?

    P.P.S.: Da du anscheinend nicht der aufmerksamste Leser bist, noch einmal als Klartext: Du hast derzeit ganz andere Probleme, als einen C-Wrapper um eine C++-Klasse zu schreiben.



  • Hallo,

    Samuel_gast schrieb:

    Wie mache ich das denn in C, wenn die Klasse CPerson noch von 3 Klassen erbt?

    Du scheinst noch nicht (richtig) verstanden zu haben, was ein Wrapper ist?!
    Du brauchst in C keinen Nachbau der C++-Klassen anlegen, sondern du "wrappst" einfach nur einen Zeiger innerhalb einer Struktur (also genauso wie bei dem Sensor-Wrapper)!
    Technisch gesehen könntest du in C auch einfach

    typedef void* Wrapper;
    

    benutzen, aber dann wäre es nicht mehr eindeutig, welcher C++-Typ darin gewrappt wird, also legt man jeweils eine eigene Struktur mit einem "void *" ("void Zeiger") an.

    Puh, langsam weiß ich nicht mehr, wie ich es dir noch näher beschreiben soll...



  • Hallo alle zusammen,

    hier noch mal meinen Versuch :

    //c_DLL_Wrapper // Header File
    #include <QObject>
    #include <QString>
    #include <QList>
    #include <QWaitCondition>
    #include <QMutex>
    
    /* building a DLL */
    #define DLLIMPORT __declspec (dllexport)
    #ifdef __cplusplus
       extern "C" { /* using a C++ compiler */
    #endif
    		// Wrapper DLL_Lib
    		typedef struct Lib DLL_Lib;
    		DLLIMPORT DLL_Lib* create_DLL_Lib(bool an_aus, QString &strFileSettings = QString("file.ini"));
    		DLLIMPORT void destory_DLL_LibWrapper(DLL_Lib* LV_ref_DLL_Lib);
    		//Wrapper CSensor
    		struct CSensor_Wrapper
    		{
    			void *CSensor;
    		};
    		DLLIMPORT CSensor_wrapper createCSensor_wrapper();
    		DLLIMPORT void destory_CSensor_Wrapper(CSensor_Wrapper* LV_ref_CSensor);
    		// Wrapper CPerson
    		struct CPerson_Wrapper
    		{
    			void * CPerson;
    		};
    		DLLIMPORT CPerson_Wrapper createCPerson_Wrapper();
    		DLLIMPORT void destory_CPerson_Wrapper(CPerson_Wrapper* LV_ref_CPerson);	
    
    		DLLIMPORT const char* DLL_LibGetVersion(DLL_Lib* LV_ref);
    		DLLIMPORT const char* DLL_LibPower(DLL_Lib* LV_ref, bool boPower);
    		DLLImport CSensor_wrapper DLL_LibSetDefault(); 
    		...
    		#ifdef __cplusplus
       }
    #endif
    #endif
    

    und die Source datei sieht so aus:

    //Source Dateien   c_DLL_Wrapper
    #include "c_DLL_Wrapper.h"
    //// Wrapper DLL_Lib
    DLLIMPORT DLL_Lib* create_DLL_Lib(bool an_ous, QString &strFileSettings_p)// ToDo QString ist kein C Datentyp
    {
    	return new Lib(an_ous, strFileSettings_p);
    }
    DLLIMPORT void destory_DLL_LibWrapper(DLL_Lib* LV_ref_DLL_Lib)
    {
    	delete LV_ref_DLL_Lib;
    }
    //Wrapper CSensor
    DLLIMPORT CSensor_wrapper createCSensor_wrapper()
    {
      CSensor_Wrapper sensor_wrapper;
    
      CSensor* sensor = new CSensor(new CPerson(CPerson::Spezifikation_A, CDirection::Stop, CAsic::BnFk)); // <-- hier noch passende Parameter angeben
      sensor_wrapper.Csensor = static_cast<void *>(sensor);
    
      return sensor_wrapper;
    }
    DLLIMPORT void destory_CSensor_Wrapper(CSensor_Wrapper* LV_ref_CSensor)
    {
    	delete LV_ref_CSensor;
    }
    //Wrapper CPerson
    DLLIMPORT CPerson_Wrapper createCPerson_Wrapper()
    {
      CPerson_Wrapper sensor_wrapper;
    
      CPerson* person = new CPerson(CPerson::Spezifikation_A, CDirection::Stop, CAsic::BnFk); // <-- hier noch passende Parameter angeben
      sensor_wrapper.CPerson = static_cast<void *>(person);
    
      return sensor_wrapper;
    }
    DLLIMPORT void destory_CPerson_Wrapper(CPerson_Wrapper* LV_ref_CPerson)
    {
    	delete LV_ref_CPerson;
    }
    
    DLLIMPORT const char* DLL_LibGetVersion(DLL_Lib* LV_ref)
    {
    	return LV_ref->LibGetVersion().toUtf8().constData();
    }
    
    DLLIMPORT void DLL_LibPower(DLL_Lib* LV_ref, bool boPower_p)
    {
    	return LV_ref->LibPower(boPower_p);
    }
    
    DLLIMPORT CSensor DLL_LibSetDefault(DLL_Lib* LV_ref)
    {
    	return LV_ref->LibSetDefault();
    }
    

    was mir nicht so ganz klar ist folgende:

    DLLIMPORT CSensor_wrapper createCSensor_wrapper()
    {
      CSensor_Wrapper sensor_wrapper;
    
      CSensor* sensor = new CSensor(new CPerson(CPerson::Spezifikation_A, CDirection::Stop, CAsic::BnFk)); // <-- hier noch passende Parameter angeben
      sensor_wrapper.Csensor = static_cast<void *>(sensor);
    
      return sensor_wrapper;
    }
    

    das Object CSensor ist schon mit der richtigen Konstrukt erzeugt aber wie hole ich mir die Daten von der copy Konstrukt
    Da (Klasse) CPerson sieht so aus:

    class CPerson: public CZeit, public CGeld, public CTier
    {
    	public:
    	typedef enum Produkt{ undef, Spezifikation_A, Spezikatation_B, Spezifikation_C} t_Produkt;
    	typedef enum PassendeZeit { SystemStart, SystemPause} t_PassendeZeit;
    	......
    	CPerson(t_Produkt enProdukt = Spezifikation_A, t_Kombination Kombination = testErfolg, t_AsicType asictype = HLM2012 ): CKombination(Kombination),CAsicSort(asictype)
    	{
    		Produkttype(Spezifikation_A);
    		DefaultValues();
    	}
    	CPerson (const CPerson &e, const CKombination &k, const CAsicSort &a): CCAsicSort(a),CKombination(k) 
    	{
    		.....
    
    	}
    	//Getter
    	....
    	// Setter
    	.....
    };
    

    und die Zweite Frage ist, bei dieser Funktion bekomme ich eine Konvertierung Problem

    DLLIMPORT CSensor DLL_LibSetDefault(DLL_Lib* LV_ref)
    {
    	return LV_ref->LibSetDefault();
    }
    

    Danke in Voraus



  • Samuel_gast schrieb:

    //c_DLL_Wrapper // Header File
    #include <QObject>
    #include <QString>
    #include <QList>
    #include <QWaitCondition>
    #include <QMutex>
    

    Das ist C++... Das wird so nicht funktionieren.



  • @Th69
    Hallo,
    auf eine Antwort von dir werde ich mich freuen



  • Hallo Samuel_gast,

    so wird das leider nichts bei deinem Code.

    Am besten du fängst mal neu mit einer Funktion an, welche keine anderen Abhängigkeiten hat (den Rest des Codes entfernen!), z.B.

    #define BOOL int
    
    typedef struct Lib_Wrapper
    {
      void *lib;
    } Lib_Wrapper;
    
    DLLIMPORT Lib_Wrapper create_Lib(BOOL an_aus, const char *fileSettings);
    

    Diese Funktion dann ausprogrammieren und schon mal mit Labview testen.
    Wenn das dann funktioniert (und du es verstanden hast), dann nach und nach die anderen Funktionen implementieren.

    Und tue dir selbst einen Gefallen, und benutze für die erzeugte Header-Datei einen C-Compiler (damit du ja keine C++-Features benutzt!), z.B. den Online-Compiler ideone.com.

    Edit: hier ein Beispiel für obigen Code: http://ideone.com/qGrMHL
    (einzig ein Linker-Fehler (+ eine hier zu vernachlässigende Warnung), weil eben die Implementation der Funktion nicht vorliegt - diese soll ja auch mit einem C++-Compiler erstellt werden).



  • Hallo,

    @Th69 10000 Dank

    Es tur mir leid, wenn ich dich störe aber ich komme leider nicht weiter 😞
    Sorry noch mal .
    Ich habe deine Rat gefolgt und habe ich jede Schritt in Labview getestet.
    Ich bin an der folgende Problem stehen geblieben.
    Header File:

    /* building a DLL */
    #define DLLIMPORT __declspec (dllexport)
    #ifdef __cplusplus
       extern "C" { /* using a C++ compiler */
    #endif
    		// Wrapper DLL_Lib
    		typedef struct Lib_Wrapper
    		{
    			void *Lib
    		}Lib_Wrapper;
    
    		const char * setting = "file.ini";
    		DLLIMPORT DLL_Lib* create_DLL_Lib(bool an_aus, const char *strFileSettings = setting);
    		DLLIMPORT void destory_DLL_LibWrapper(DLL_Lib* LV_ref_DLL_Lib);
    		DLLIMPORT const char* DLL_LibGetVersion(DLL_Lib* LV_ref); 
    
       #ifdef __cplusplus
       }
    #endif
    #endif
    

    Beim Quellencode:

    #include "c_DLL_Wrapper.h"
    //// Wrapper DLL_Lib
    DLLIMPORT DLL_Lib create_DLL_Lib(bool an_ous, const char *strFileSettings)
    {
    	Lib_Wrapper lib_Wrapper;
      Lib* lib = new Lib(an_aus,QString::QString (strFileSettings)); // <-- hier noch passende Parameter angeben
      //Lib* lib = new Lib(an_aus,strFileSettings); 
      lib_Wrapper.Lib = static_cast<void *>(lib);
    
      return lib_Wrapper;
    }
    DLLIMPORT void destory_DLL_LibWrapper(DLL_Lib* LV_ref_DLL_Lib)
    {
    	delete LV_ref_DLL_Lib;
    }
    

    Bei der Methode:

    create_DLL_Lib(bool an_ous, const char *strFileSettings)
    

    Wenn ich so schreibe:

    Lib* lib = new Lib(an_aus,strFileSettings);
    

    kriege ich einen Konvertierungsproblem:
    cannot convert parameter 2 from 'const char *' to 'QString &'



  • Samuel_gast schrieb:

    kriege ich einen Konvertierungsproblem:
    cannot convert parameter 2 from 'const char *' to 'QString &'

    Dazu muss aus dem const char* ein QString werden.
    Und an dieses temporary kannst Du keine (non-const!) Referenz binden.

    Das ist zu Deinem eigenen Schutz:
    jede Veränderung, die Du - via die Referenz - an dem temporary vornimmst ist ja sofort verloren, sobald seine Lebensdauer endet.



  • Furble Wurble schrieb:

    Samuel_gast schrieb:

    kriege ich einen Konvertierungsproblem:
    cannot convert parameter 2 from 'const char *' to 'QString &'

    Dazu muss aus dem const char* ein QString werden.
    Und an dieses temporary kannst Du keine (non-const!) Referenz binden.

    Das ist zu Deinem eigenen Schutz:
    jede Veränderung, die Du - via die Referenz - an dem temporary vornimmst ist ja sofort verloren, sobald seine Lebensdauer endet.

    und was heisst das genau 😮 ?



  • Ohne jetzt den gesamten Thread gelesen zu haben:
    Dein Lib Konstruktor sieht irgendwie so aus:

    Lib::Lib(bool, QString&)
    {
      //...
    }
    

    Und das QString& kann nicht so bleiben.
    Was passiert denn mit dem Parameter?
    Je nachdem ist Lib::Lib(bool, const QString&); oder Lib::Lib(bool, QString); richtiger.



  • Derjenige der die C++-Lib erstellt hat, hat leider kein "const QString&" (bzw. gleich "QString") als Parameter genommen, sondern eine nicht-konstante Referenz (Grund wahrscheinlich Unwissenheit!).

    Du mußt also beim Aufruf selber eine Variable vom Typ QString erstellen und diese dann übergeben:

    QString str(strFileSettings);
    Lib* lib = new Lib(an_aus, str);
    

    PS: Dein Header ist immer noch falsch, denn C unterstützt keine Default-Parameter (const char *strFileSettings = setting). Wenn dann müßtest du zwei verschiedene Funktionen (mit unterschiedlichem Namen) dafür anbieten (und die eine ruft die andere dann mit "file.ini" als 2. Parameter auf)!
    Und C (zumindestens C89) kennt kein "bool", daher habe ich extra ein #define dafür angelegt (als int).
    Noch ein letztes Mal: teste den Header mit einem C-Compiler, sonst wird LabView beim Aufruf der Funktionen falsche Parameter übergeben (und dies ist Undefined Behaviour (UB) und könnte deinen Rechner formatieren oder "Dämonen aus der Nase fliegen lassen"...).

    PPS: Was ist denn jetzt überhaupt "DLL_Lib" bei dir? Du verwendest den extra deklarierten "Lib_Wrapper" ja gar nicht!!!

    Das wird eine harte Lernkurve für dich - ich hoffe aber, daß du so langsam dahinterkommst?!



  • Th69 schrieb:

    Derjenige der die C++-Lib erstellt hat, hat leider kein "const QString&" (bzw. gleich "QString") als Parameter genommen, sondern eine nicht-konstante Referenz (Grund wahrscheinlich Unwissenheit!).

    Ahh...
    Jetzt rächt sich, dass ich nur von der fehlerhaften Konvertierung getriggert worden bin, ohne den Thread gelesen zu haben.

    Ich dachte der TE hätte die Kontrolle über die Konstruktoren.


Anmelden zum Antworten