# dll mit Dev C++ erstellen und aufrufen



## xkris (14. August 2007)

Hallo zusammen,

 ich versuche grad mit dem Dev C++  ein DLL Projekt erstellen:


```
//dllmain.h
#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 my_class
{
  public:
    my_class();
    virtual ~my_class(void);
    
    void function1(parameter..);
    void function2(parameter..);
  private:

};


#endif /* _DLL_H_ */
```

und


```
//dllmain.cpp
/* Replace "dll.h" with the name of your header */
#include "dll.h"
#include <windows.h>

my_class::my_class()
{
    ....
}


my_class::~my_class ()
{
    ....
}


void my_class::function1(parameter...)
{
    ....
}


void my_class::function2(parameter...)
{
    ....
}

BOOL APIENTRY DllMain (HINSTANCE hInst     /* Library instance handle. */ ,
                       DWORD reason        /* Reason this function is being called. */ ,
                       LPVOID reserved     /* Not used. */ )
{
    switch (reason)
    {
      case DLL_PROCESS_ATTACH:
        break;

      case DLL_PROCESS_DETACH:
        break;

      case DLL_THREAD_ATTACH:
        break;

      case DLL_THREAD_DETACH:
        break;
    }

    /* Returns TRUE on success, FALSE on failure */
    return TRUE;
}
```

Kompilieren lässt sich das Ganze problemlos.
Wenn ich allerdings versuche, auf eine Funktion der DLL zuzugreifen, funktionierts nicht.

Der Zugriff soll dynamisch erfolgen. Zu Testzwecken definiere ich zunächst einen Zeiger auf eine der DLL Funktionen und Deklariere eine Variable dieses neuen Typs.
Mit new_handle lade ich die DLL. Das funktioniert noch. Wenn ich allerdings mit GetProcaddress auf die konkrete Funktion zugreifen will bekomme ich immer nur _null_ statt der Adresse der Funktion


```
#include <cstdlib>
#include <iostream>
#include <windows.h>

using namespace std;

typedef void(__stdcall *P_function1) (parameter...); 
P_function1 m_function1;

HINSTANCE new_handle = NULL;


int main(int argc, char *argv[])
{
    
    
    
    
    new_handle = LoadLibrary("myDLL.dll");
    
    
    
    if (!new_handle) 
       cout<<"dll nicht geladen"<<endl;
    else
        m_function1=(P_function1) GetProcAddress (new_handle,"function1");
      
    cout<<m_function1<<endl;   //gibt null aus
    system("PAUSE");
    return EXIT_SUCCESS;
}
```

Weiss möglicherweise von euch jemand, wo der Fehler liegen könnte?

gruß
kristian


----------



## deepthroat (14. August 2007)

xkris hat gesagt.:


> Weiss möglicherweise von euch jemand, wo der Fehler liegen könnte?


Das Problem ist, das es keine Funktion "function1" gibt. Es gibt eine Methode, die zur Klasse my_class gehört namens "function1". 

Selbst wenn du einen Zeiger auf die Methode hättest, kann diese Methode bzw. Memberfunction nicht ohne eine Instanz der Klasse aufgerufen werden. Zumal hast du den Zeigertyp P_function1 falsch defniert, denn bei einer Methode wird immer als erster Parameter noch ein Zeiger auf die Instanz der Klasse übergeben. Und zu guter letzt wird der Name von Funktionen und Klassen in C++ noch "gemangled" - den Namen kann man dann in der def Datei sehen.

Was du machen könntest, ist für jede Memberfunktion eine Wrapper-Funktion (mit extern "C") in der DLL zu definieren die erstens einen Zeiger auf eine Instanz und die entsprechenden Parameter bekommt. Diese Funktion ruft dann innerhalb der DLL die Memberfunktion auf und gibt entsprechend das Ergebnis zurück. 

Außerdem brauchst du dann noch eine Funktion die einen Zeiger auf ein neues my_class Objekt zurückgibt und evtl. eine Funktion die dieses Objekt wieder zerstört.


```
extern "C"
{
   __declspec(dllexport) void f(void* p, parameter...)
   {
      reinterpret_cast<MyClass*>(p)->mf(parameter...);
   }
}
```

Gruß


----------



## xkris (14. August 2007)

Hallo und Danke für deine Hilfe. Ich habe noch ein Verständnisproblem was folgendes Konstrukt betrifft:


```
#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllimport)
#endif /* Not BUILDING_DLL */
```

Der erste Teil ist klar: 

#if BUILDING_DLL...

Also wird vor dem Kompilieren DLLIMPORT durch __declspec (dllexport) ersetzt. 
Aber was soll der else-Zweig. Was genau soll hier in die DLL importiert werden? Gehört die Import-Anweisung wenn überhaupt nicht in eine Anwendung, die die Funktionen, die von der DLL bereitgestellt werden, importiert?

Alles sehr verwirrend...

Gruß

kristian


----------



## deepthroat (14. August 2007)

xkris hat gesagt.:


> Hallo und Danke für deine Hilfe. Ich habe noch ein Verständnisproblem was folgendes Konstrukt betrifft:
> 
> 
> ```
> ...


In der DLL wird gar nichts importiert (in diesem Fall). Nur include'st du die Headerdatei ja auch in dem Projekt, das dann die DLL benutzen soll. Und da wird dann die dllimport Deklaration verwendet.

Gruß


----------



## xkris (14. August 2007)

deepthroat hat gesagt.:


> In der DLL wird gar nichts importiert (in diesem Fall). Nur include'st du die Headerdatei ja auch in dem Projekt, das dann die DLL benutzen soll. Und da wird dann die dllimport Deklaration verwendet.
> 
> Gruß



Ich hab die Header-Datei aber nicht in mein Projekt "included". Der Zugriff erfolgt dynamisch und dafür brauch ich die Header-datei eigentlich nicht. Wird sie evt. benötigt um die DLL statsich zu laden?

gruß
kristian


----------



## deepthroat (14. August 2007)

xkris hat gesagt.:


> Ich hab die Header-Datei aber nicht in mein Projekt "included". Der Zugriff erfolgt dynamisch und dafür brauch ich die Header-datei eigentlich nicht. Wird sie evt. benötigt um die DLL statsich zu laden?


Ja, natürlich. Der Linker muss schließlich darüber informiert sein, wie die Symbole die verwendet aufgelöst werden können.

Gruß


----------

