dlls mit Klassen?



  • Ich will ne dll schreiben, aber meine Klassen weiterverwenden. Ohne die Klassen läuft die dll prima, mit gcc (Dec-cpp) kompiliert. Jetzt mit den Klassen benutze ich den g++ (Dev-cpp) und nun will die dll nicht mehr, obwohl ich keine Änderungen vorgenommen habe, nur den Code komplett kopiert. Gibts da was, was man beachten muss?



  • den dll export rausnehmen. ansonsten versuche es mal genauer zu beschreiben was du machen möchtest, etvl. ein beispiel



  • Ich hab mit dev-cpp ne dll mit c++ als sprache erstellt.
    Der Gegebene Code siet so aus:

    #ifndef _DLL_H_
    #define _DLL_H_
    
    #if BUILDING_DLL
    # define DLLIMPORT __declspec (dllexport)
    #else /* Not BUILDING_DLL */
    # define DLLIMPORT __declspec (dllimport)
    #endif /* Not BUILDING_DLL */
    
    class DLLIMPORT DllClass
    {
      public:
        DllClass();
        virtual ~DllClass(void);
    
      private:
    
    };
    
    #endif
    

    den hab ich komplett gelöscht, und mit meinem Code aus dem ehemals-c-projekt ersetzt:

    #ifndef _DLL_H_
    #define _DLL_H_
    
    /*--------------------------------------------------------------------------*/
    /*      Includes                                                            */
    /*--------------------------------------------------------------------------*/
    
    #include <windows.h>
    #include <prsht.h>
    
    /*--------------------------------------------------------------------------*/
    /*      Defines                                                             */
    /*--------------------------------------------------------------------------*/
    
    /*#if BUILDING_DLL
    # define DLLIMPORT __declspec (dllexport)
    #else /* Not BUILDING_DLL */
    /*# define DLLIMPORT __declspec (dllimport)
    #endif /* Not BUILDING_DLL */
    
    /*--------------------------------------------------------------------------*/
    /*      Prototypen                                                          */
    /*--------------------------------------------------------------------------*/
    
        // Hauptfunktionen der Miranda-Dll
    __declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion);
    int __declspec(dllexport) Load(PLUGINLINK *link);
    int __declspec(dllexport) Unload(void);
    
    #endif
    

    problem:
    Dll wird von Applikation (Miranda) nicht mehr geladen, bzw. gar nicht erkannt!
    Ich kann dir auch den ganzen Code zukommen lassen, das ja sowieso Open Source wird...



  • immernoch noch ganz kapiert. aber wenn du c funktion exportieren willst wäre es ratsam diese mit

    extern "C"
    {
    
    }
    

    zu umklammern.
    möchtest du jetzt eine c oder ein c++ dll erstellen? soll diese klassen exportieren? möchtest ein c++ klassenplugin schreiben?

    [edit]
    rechtschreibung



  • also, mit der extern deklaration lädt es die klasse schon mal
    danke 👍



  • wie müsste denn eine C++ dll aufgebaut sein?
    muss ich da alle Funktionen einfach in die Klasse wie oben beschrieben packen?



  • Objekte aus ner dll zu exporteiren ist nicht wirklich zu empfehlen, weil es probleme geben kann wenn du mit verschiedenen linkern arbeitetest, auch dynamisches laden fällt flach.
    Der übebliche weg ist ein c-interface zum erzeugen der objecte:

    #if BUILDING_DLL
    # define DLLIMPORT __declspec (dllexport)
    #else /* Not BUILDING_DLL */
    # define DLLIMPORT __declspec (dllimport)
    #endif /* Not BUILDING_DLL */
    
    class IDllClass
    {
      public:
        virtual ~IDllClass() = 0;
        virtual void func() = 0;
    };
    
    // erzeugt eine instanz deiner klasse
    DLLIMPORT IDllClass* CreateDllClass();
    

    Ne andere möglichkeit ist COM, ist zwar etwas aufwendiger, löst aber auch gleich ne mange anderer probleme, wie kompatibilität mit anderen sprachen, marshaling, RPCs,..



  • jep.
    schau dir halt nochmal das example von devcpp an.



  • problem: miranda ist total c-basiert und wird wohl kaum eine Instanz meiner Klasse erstellen wollen



  • das macht die dll.

    Nur damit ich es auch verstehe: du willst in deiner dll c++ verwenden und die dll in nem c prog verwendet? was hindert dich dann daran der dll ein c interface zu geben und intern c++ zu verwenden?



  • Ähh, Unkenntnis, würd ich sagen.
    Ich hab nu alle Funktionen, die vom Prog aufgerufen werden müssen in die exter "C" Schleife gesetzt. Funktioniert alles wunderbar, bis auf dass eine Resource-Datei nicht mehr korrekt bearbeitet wird. In der Datei stehen Anweisungen für ein property sheet, welches nun nicht mehr angezeigt wird. Würde das mit der von dir vorgeschlagenen Interface-Geschichte gelöst werden, und wenn ja, könntest du ein Beispiel geben?



  • Also, beim Versuch, die property sheet page zu erstellen, wird Fehler 1008:
    An attempt was made to reference a token that does not exist. ERROR_NO_TOKEN
    geliefert. Hat jemand ne Idee?



  • idee keine. 😃
    code?!?



  • int HookProc(WPARAM wParam,LPARAM lParam)
    {
            // Seite vorbereiten
        OPTIONSDIALOGPAGE odp={
                          sizeof(OPTIONSDIALOGPAGE),
                          0,
                          OPTION_NAME,
                          DialogProc,
                          MAKEINTRESOURCE(IDD_DIALOG1),
                          hInst, NULL, "Plugins", 1, NULL, PSP_DEFAULT, 
                          0, 0, 
                          NULL, 0};
            // Seite den Optionen hinzufügen
        CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)(OPTIONSDIALOGPAGE*) &odp);
        #ifdef DEBUG
        char temp[50];
        wsprintf (temp, "%d", GetLastError ());
        MessageBox (NULL, temp, "Fehler", MB_OK);
        #endif
        return 0;
    }
    

    Die DialogProc wird aber nie aufgerufen.



  • wenn du eigene strukturen und befehle nimmst müsstest diese auch erklären. 🙄



  • naja, das sind nicht meine, aber ich kann ja das posten, was ich hab:

    In Miranda gibts ne Reihe vordefiniertet "Services", die als Strings in der
    Datenbank registriert sind. Man kann einen Service mit CallService aufrufen. Dabei übergibt man den String, der den Service identifiziert und 2 Parameter.
    Der untenstehende Service AddPage fügt ein property sheet in das Optionsmenü von Miranda ein. Im Prinzip ne feine Sache, man muss nur das untenstehende struct füllen, die Seite verhält sich dann ganz normal wie ein property sheet.
    Kurze Erläuterung der (wichtigen) Variabeln:
    cbSize = Größe der Struktur
    pszTitle = Titel der Seite im Auswahlmenü
    pfnDlgProc = Das DialogProc
    pszTemplate = Pointer auf eine Resource, ganz wie bei normalen ps
    hInstance = Instanz des ps, wird von DllMain geliefert
    flags = Flags ebenfalls wie beim ps

    /* Opt/AddPage
    Must only be called during an opt/initialise hook
    Adds a page to the options dialog
    wParam=addInfo
    lParam=(LPARAM)(OPTIONSDIALOGPAGE*)odp
    addInfo must have come straight from the wParam of opt/initialise
    Pages in the options dialog operate just like pages in property sheets. See the
    Microsoft documentation for details on how they operate.
    Strings in the structure can be released as soon as the service returns, but
    icons must be kept around. This is not a problem if you're loading them from a
    resource.
    Prior to v0.1.2.1 the options dialog would resize to fit the largest page, but
    since then it is fixed in size. The largest page that fits neatly is 314x240
    DLUs.
    */
    #define OPTIONSDIALOGPAGE_V0100_SIZE   0x18
    #define OPTIONSDIALOGPAGE_V0120_SIZE   0x28
    typedef struct {
    	int cbSize;
    	int position;        //a position number, lower numbers are topmost
    	char *pszTitle;
    	DLGPROC pfnDlgProc;
    	char *pszTemplate;
    	HINSTANCE hInstance;
    	HICON hIcon;		 //v0.1.0.1+
    	char *pszGroup;		 //v0.1.0.1+
    	int groupPosition;	 //v0.1.0.1+
    	HICON hGroupIcon;	 //v0.1.0.1+
    	DWORD flags;         //v0.1.2.1+
    	int nIDBottomSimpleControl;  //v0.1.2.1+  if in simple mode the dlg will be cut off after this control, 0 to disable
    	int nIDRightSimpleControl;  //v0.1.2.1+  if in simple mode the dlg will be cut off after this control, 0 to disable
    	UINT *expertOnlyControls;
    	int nExpertOnlyControls;    //v0.1.2.1+  these controls will be hidden in simple mode. Array must remain valid for duration of dlg.
    } OPTIONSDIALOGPAGE;
    #define ODPF_SIMPLEONLY   1	  //page is only shown when in simple mode
    #define ODPF_EXPERTONLY   2	  //         "                 expert mode
    #define ODPF_BOLDGROUPS   4   //give group box titles a bold font
    
    #define PSN_EXPERTCHANGED 2    //sent to pages via WM_NOTIFY when the expert checkbox is clicked. lParam=new state
    #define PSM_ISEXPERT      (WM_USER+101)   //returns true/false
    #define PSM_GETBOLDFONT   (WM_USER+102)   //returns HFONT used for group box titles
    #define MS_OPT_ADDPAGE      "Opt/AddPage"
    

    Muss dazu sagen, dass das wunderbar funktioniert hat, bis ich den Quellcode mit g++ compiliert hab, und dafür alle Funktionen mit exter "C" deklarieren musste.



  • N00Bie schrieb:

    Muss dazu sagen, dass das wunderbar funktioniert hat, bis ich den Quellcode mit g++ compiliert hab, und dafür alle Funktionen mit exter "C" deklarieren musste.

    ich muss ehrlich sagen ich verstehe nicht warum du mit aller gewalt aus einer c dll eine c++ machen möchtest wenn das programm das diese dann verwendet vermutlich auch in c geschrieben ist. 😕 ich sehe darin keinen vorteil nur riesige nachteile.

    ich vermute das diese struktur in einem exteren header ist, diesen musst du dann auch umklammern

    extern "C"
    {
        #include "derheader.h"
    }
    


  • miller_m schrieb:

    ich muss ehrlich sagen ich verstehe nicht warum du mit aller gewalt aus einer c dll eine c++ machen möchtest wenn das programm das diese dann verwendet vermutlich auch in c geschrieben ist. 😕 ich sehe darin keinen vorteil nur riesige nachteile.

    Weil ich dann alle Header neu Coden müsste. Im Prinzip will ich ja keine C++ dll, sondern nur eine Möglichkeit meine C++ Header mit der C-Dll zu verwenden.

    Die Header hab ich mit im extern "C" {} drin.



  • N00Bie schrieb:

    Weil ich dann alle Header neu Coden müsste. Im Prinzip will ich ja keine C++ dll, sondern nur eine Möglichkeit meine C++ Header mit der C-Dll zu verwenden.

    was verstehst du unter c++ und c header? mach mal ein beispiel



  • c-header:

    #ifndef _HEADER_H
    #define _HEADER_H
    
    void Funktion (char * buffer);
    
    #endif
    

    einer meiner cpp-header:

    #ifndef _TRC4_H_
    #define _TRC4_H_
    
    /*--------------------------------------------------------------------------*/
    /*      Includes                                                            */
    /*--------------------------------------------------------------------------*/
    
    #include "TEngine.h"
    
    /*--------------------------------------------------------------------------*/
    /*      Klasse                                                              */
    /*--------------------------------------------------------------------------*/
    
    class TRC4 : public TEngine
    {
    private:
    	long Init();
    	void swap( BYTE & x, BYTE & y );
    
    	BYTE SBox[SBOX_LENGTH];
    	BYTE K[SBOX_LENGTH];
    public:
    	virtual ~TRC4();
    
    	TRC4();
    
    	virtual long Encrypt( char * buffer, long length );
    
    	virtual long Decrypt( char * buffer, long length );
    
    };
    
    #endif
    

Anmelden zum Antworten