www.mikrocontroller.net

Forum: PC-Programmierung DLL in C++ schreiben


Autor: peterguy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Forum,

ich möchte eine DLL erstellen mit C++ (nicht C).
Habe mir die Visual Studio 2008 C+++ Express Edition besorgt und erste 
Gehversuche unternommen. Vom Prinzip her klappt die erste Version der 
DLL, aber ich bin mit dem Code an sich ziemlich unzufrieden.

Da ich in der Objektorientierten Welt noch neu bin (bisher nur 
strukturiert programmiert), tue ich mich mit dem Programieren unter C++ 
recht schwer.

Hat vielleicht jemand schon mal eine kleine DLL in C++ geschrieben und 
würde den Sourcecode hier veröffentlichen? Es geht mir darum, ein paar 
Ideen / Inspirationen zu bekommen, deswegen ist es eigentlich egal was 
die DLL macht.

Also, immer her mit eurem Beispielcode :-)

: Verschoben durch Moderator
Autor: Mathias R. (prinz77) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gugst du hier -> www.sourceforge.net

Ich würde mal sagen da dümpeln mehr als genug DLL's rum.

Ob die nun gut oder schlecht programmiert sind liegt wohl im Auge des 
Betrachters. :D

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich versteh nicht ganz wo das Problem liegt.

ob das ganze in einer Dll ist oder nicht spielt doch keine Rolle. Hast 
du generell ein Problem bei der Programmierung in C++ oder willst du die 
Dll Dynmisch laden?

Wenn du sie dynamsich laden willst, macht du am besten eine C 
schnittstelle und verwendest einfach eine C funktion die dir ein object 
zurück gibt.

object x = (dll).GetObject()

danach kannst du mit x alles machen was c++ erlaubt.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du objektorientiert und DLLs zusammenbringen willst, dann hier
was zum Probieren:

Es gibt ein Hauptprogramm, das zu einer EXE wird und nur eine
Basisklasse kennt (Base).

Eine abgeleitete Klasse Derived (dem Hauptprogramm gänzlich unbekannt)
wird in einer DLL (bzw. "shared object" in Linux) definiert.

Das Hauptprogramm lädt die DLL, holt sich über eine create()-Funktion
wie von Peter vorgeschlagen ein Objekt der abgeleiteten Klasse und
ruft daraus eine Methode auf, obwohl Derived ihm unbekannt ist.

Sinnvollerweise würde man Base auch gleich in einer DLL ablegen, weil
es so wie hier gezeigt sowohl zur EXE als auch zur DLL gelinkt werden
muß, aber das ist mir jetzt zuviel Aktion.
Die DLL mit Base würde man zum Hauptprogramm ebenso wie zur
Derived-DLL statisch linken, also nicht dynamisch zur Laufzeit holen.

Das Hauptprogramm:
// Time-stamp: "17.08.09 10:07 dll_dynload_base.cpp klaus?wachtler.de"
//
// Beispiel für die Verwendung einer DLL, die eine Ableitung
// definiert.
//
// In diesem Quelltext wird die Basisklasse verwendet, eine DLL
// dynamisch geladen in der davon eine Ableitung definiert ist und ein
// derartiges Objekt erzeugt wird.
//
// Kompilieren unter Linux:
//   g++ -Wall dll_dynload_base.cpp Base.cpp -ldl -o dll_dynload_base
//
// Aufruf unter Linux (funktioniert nur, wenn auch Derived.plugin_so bereits
// erzeugt wurde, siehe Derived.cpp):
//   ./dll_dynload_base
//
// Kompilieren unter Windows mit VC++ VS2005:
//   cl /EHsc dll_dynload_base.cpp Base.cpp
//
// Aufruf unter Windows (funktioniert nur, wenn auch
// Derived.plugin_win bereits erzeugt wurde, siehe Derived.cpp):
//   dll_dynload_base.exe

#include <iostream>

#include "Base.h"


#if defined  __GNUC__
#include <dlfcn.h>
#elif defined _WIN32
#include <windows.h>
#include <winuser.h>
#endif



int main( int nargs, char **args )
{
  // Base ist hier bekannt, kann direkt verwendet werden:
  Base    einBase( 25 );
  einBase.tuwas();

  // Ein Derived-Objekt kann über die DLL angesprochen werden:

#if defined  __GNUC__
  // DLL laden, Linux-Version:
  void *plugin_handle = dlopen( "./Derived.plugin_so", RTLD_NOW );
#elif defined _WIN32
  // DLL laden, Windows-Version:
  HINSTANCE plugin_handle = LoadLibrary( ".\\Derived.plugin_win" );
#endif
  if( !plugin_handle )
  {
    std::cerr << "kann Plugin nicht laden" << std::endl;
  }
  else
  {
    // Typ der create()-Funktion:
    typedef Base*(*plugin_create_fp_t)();
#if defined  __GNUC__
    // Zeiger auf create() holen, Linux-Version:
    plugin_create_fp_t   plugin_create_fp = (plugin_create_fp_t)dlsym( plugin_handle,
                                                                       "create"
                                                                       );
#elif defined _WIN32
    // Zeiger auf create() holen, Windows-Version:
    plugin_create_fp_t   plugin_create_fp
      = (plugin_create_fp_t)GetProcAddress( plugin_handle,
                                            "create"
                                            );
#endif

    if( !plugin_create_fp )
    {
      std::cerr << "Funktion nicht in DLL gefunden" << std::endl;
    }
    else
    {
      // Objekt der abgeleiteten Klasse Derived über die create()-Funktion
      // erzeugen lassen:
      Base *p_Object = plugin_create_fp();

      p_Object->tuwas();

      delete p_Object; p_Object = NULL;
    }


    // DLL wieder freigeben:
    plugin_create_fp = NULL;
#if defined  __GNUC__
    dlclose( plugin_handle );
#elif defined _WIN32
    FreeLibrary( plugin_handle );
#endif
    plugin_handle = NULL;

  }

  return 0;
}

Die Basisklasse
// Time-stamp: "17.08.09 08:27 Base.h klaus?wachtler.de"
//
// Eine Basisklasse als Beispiel...

class Base
{
 public:

  Base( int wert = 0 );

  virtual ~Base();

  virtual void tuwas();

 protected:
  int    wert;
};

Ihre Implementation:
// Time-stamp: "17.08.09 08:14 Base.cpp klaus?wachtler.de"
//
// Implemenation der Basisklasse

#include <iostream>

#include "Base.h"

Base::Base( int wert )
  : wert( wert )
{
}

Base::~Base()
{
}

void Base::tuwas()
{
  std::cout << "ich bin ein Base, mein Wert ist " << wert << std::endl;
}

Die DLL mit der abgeleiteten Klasse:
// Time-stamp: "17.08.09 10:02 Derived.cpp klaus?wachtler.de"
//
// Quelltext einer DLL, die von Base die Klasse Derived ableitet und
// eine Funktion create() definiert, mit der ein Objekt von Derived
// erzeugt werden kann.
//
// Kompilieren unter Linux:
//   g++ -shared Derived.cpp Base.cpp -fpic -o Derived.plugin_so
//
// Kompilieren unter Windows mit VC++ VS2005:
//   cl /EHsc /LD Derived.cpp Base.cpp /FeDerived.plugin_win

#include <iostream>

#include "Base.h"

class Derived: public Base
{
public:
  Derived( int wert = 0 )
    : Base( wert )
  {
  }

  virtual void tuwas()
  {
    std::cout << "ich bin ein Derived, mein Wert ist " << wert << std::endl;
  }

  virtual ~Derived()
  {
  }

};


extern  "C"
#ifdef _WIN32
__declspec(dllexport)
#endif
Base * create()
{
  return new Derived();
}

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.