c_DLL Wrapper
-
Sollte es nicht bei deiner letzten Funktion "CSensor_wrapper *" als Rückgabetyp sein?
Jedoch hast du noch einen großen Fehler drin (und anscheinend nicht verstanden, was ein Wrapper ist): du darfst nicht einfach
typedef struct CSensor CSensor_wrapper;
schreiben!
Ein Wrapper bedeutet, daß du eine Struktur erzeugst, welche intern die Daten hält, d.h. z.B.struct Sensor_Wrapper { void *sensor; // intern ein CSensor* !!! };
Und aus deiner Wrapper-Header-Datei mußt du natürlich alle C++ Features (d.h. QT, Referenzen, ...) rausnehmen!
Edit:
Noch als Hinweis dazu: erstelle dir einfach selber ein C-Projekt, welches dann diese Header-Datei einbindet und deren Funktionen benutzt (ohne Fehler beim Kompilieren zu erzeugen - Linker-Fehler wegen fehlender Implementierung kannst du dann ersteinmal ignorieren).
-
Th69 schrieb:
Sollte es nicht bei deiner letzten Funktion "CSensor_wrapper *" als Rückgabetyp sein?
--> ja du hast rechtDLLIMPORT CSensor_wrapper DLL_LibSetDefault(DLL_Lib* LV_ref) { return LV_ref->LibSetDefault(); }
Jedoch hast du noch einen großen Fehler drin (und anscheinend nicht verstanden, was ein Wrapper ist): du darfst nicht einfach
typedef struct CSensor CSensor_wrapper;
schreiben!
Ein Wrapper bedeutet, daß du eine Struktur erzeugst, welche intern die Daten hält, d.h. z.B.struct Sensor_Wrapper { void *sensor; // intern ein CSensor* !!! };
--> Das habe ich nicht genau verstanden
Und aus deiner Wrapper-Header-Datei mußt du natürlich alle C++ Features (d.h. QT, Referenzen, ...) rausnehmen!
Edit:
Noch als Hinweis dazu: erstelle dir einfach selber ein C-Projekt, welches dann diese Header-Datei einbindet und deren Funktionen benutzt (ohne Fehler beim Kompilieren zu erzeugen - Linker-Fehler wegen fehlender Implementierung kannst du dann ersteinmal ignorieren).
-
Die QT Referenzen habe ich rausgenommen.
Th69 schrieb:
Ein Wrapper bedeutet, daß du eine Struktur erzeugst, welche intern die Daten hält, d.h. z.B.struct Sensor_Wrapper { void *sensor; // intern ein CSensor* !!! };
Konkret in meinem Code heisst das ich soll eine neu Strctur erzeugen?
deinem Beispiel habe ich aber leider nicht verstanden
-
Ja, eine neue Struktur in C erzeugen.
Und dann entsprechend befüllen bzw. auslesen:
Sensor_Wrapper* create_sensor_wrapper() { Sensor_Wrapper* sensor_wrapper = new SensorWrapper(); CSensor* sensor = new CSensor(); // <-- hier noch passende Parameter angeben sensor_wrapper->sensor = static_cast<void *>(sensor); return sensor_wrapper; } void use_sensor_wrapper(Sensor_Wrapper* sensor_wrapper) { CSensor* sensor = static_cast<CSensor*>(sensor_wrapper->sensor); // use sensor... }
(und noch ein Freigabefunktion schreiben mit delete)
Ja, das ist viel Schreibarbeit, aber anders geht es nicht...
-
ist mein struct richtig?
struct CSensor { public: //CSensor(CPerson * PPerson); ist nicht relevant für C_DLL_Wrapper CSensor(const CSensor &e) //CopyConstrucor { m_strT1 = e.m_strT1; m_strT2 = e.m_strT2; m_strT3 = e.m_strT3; m_strT4 = e.m_strT4; m_strU = e.m_strU; m_strI = e.m_strI; .... } //setter void SetT1(const char* &str_p) { m_strT1 = str_p;} void SetT2(const char* &str_p) { m_strT2 = str_p;} void SetT3(const char* &str_p) { m_strT3 = str_p;} void SetT4(const char* &str_p) { m_strT4 = str_p;} .... //getter const char* GetT1(void) const { return m_strT1; } const char* GetT2(void) const { return m_strT2; } const char* GetT3(void) const { return m_strT3; } const char* GetT4(void) const { return m_strT4; } .... private: const char* m_strT1; const char* m_strT2; const char* m_strT3; const char* m_strT4; .... };
-
Hallo,
da hast du aber jetzt wohl meinen Satz mißverstanden. Die Wrapper-Struktur mußt du neu in C erstellen, deine bisherigen C++-Klassen können bleiben wie sie sind.
Du mußt dann halt nur für die zu exportierenden Klassenfunktionen dafür dann freie Funktionen anbieten (mit der Wrapper-Struktur als (ersten) Parameter und reinen C Parametern, sog. POD).
Wenn du C++ Datentypen als Parameter durchschleusen willst (z.B. QString), dann mußt du halt auch hierfür einen Wrapper erstellen.Mir fällt aber gerade auf, daß ich oben eine Indirektion zu viel drin habe. Besser ist wohl
Sensor_Wrapper create_sensor_wrapper() { Sensor_Wrapper sensor_wrapper; CSensor* sensor = new CSensor(); // <-- hier noch passende Parameter angeben sensor_wrapper.sensor = static_cast<void *>(sensor); return sensor_wrapper; } void use_sensor_wrapper(Sensor_Wrapper sensor_wrapper) { CSensor* sensor = static_cast<CSensor*>(sensor_wrapper.sensor); // use sensor... }
(d.h. Sensor_Wrapper in C direkt verwenden, anstatt als Zeiger)
-
struct Sensor_Wrapper
{
void *sensor; // intern ein CSensor* !!!
};Wie definiere ich bitte meine "struct Sensor_Wrapper " anhand meine CSensor class
class CSensor { public: EFILIBRARY_EXPORT CSensor(CPerson * PPerson); EFILIBRARY_EXPORT CSensor(const CSensor &e) //CopyConstrucor { m_strT1 = e.m_strT1; m_strT2 = e.m_strT2; m_strT3 = e.m_strT3; m_strT4 = e.m_strT4; m_strU = e.m_strU; m_strI = e.m_strI; .... } //setter EFILIBRARY_EXPORT void SetT1(QString &str_p) { m_strT1 = str_p;} EFILIBRARY_EXPORT void SetT2(QString &str_p) { m_strT2 = str_p;} EFILIBRARY_EXPORT void SetT3(QString &str_p) { m_strT3 = str_p;} EFILIBRARY_EXPORT void SetT4(QString &str_p) { m_strT4 = str_p;} .... //getter EFILIBRARY_EXPORT QString GetT1(void) const { return m_strT1; } EFILIBRARY_EXPORT QString GetT2(void) const { return m_strT2; } EFILIBRARY_EXPORT QString GetT3(void) const { return m_strT3; } EFILIBRARY_EXPORT QString GetT4(void) const { return m_strT4; } .... private: QString m_strT1; QString m_strT2; QString m_strT3; QString m_strT4; .... };
Sorry
-
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?
-
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 einfachtypedef 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