Pluginsystem - Funktion von Hauptprogramm in .dll aufrufen nur mit prototyp in .h - linker error
-
Hallo,
ich suche schon ca. eine Stunde nach Beiträgen zu diesem Problem, konnte aber keine finden.
Folgendes: Ich habe eine Anwendung (Konsolenanwendung - .exe) und eine DLL die ein Plugin realisiert. Das Plugin wird von der Anwendung per LoadLibrary() reingeladen und registriert 2 funktionen, über funktionen des hauptprogramms register_init_plugin() und register_cleanup_plugin(). Sprich ich includiere den Header aus dem Hauptprogramm damit ich die Prototypen im Plugin Quellcode zur Verfügung habe.
Unter Linux ging das einwandfrei, da hat der Linker nicht gemeckert wenn er keine Referenzen hatte, weil er wusste, es ist ein shared object und der Code liegt woanders (in meinem Fall IN dem Hauptprogramm). Visual C++ .NET 2003, meckert aber, es gäbe 2 unaufgelöste Verweise auf die oben genannten Funktionen. Natürlich hab ich keine .lib...wieso auch, ich will ja NUR Funktionen des Hauptprogramms aufrufen. Ich kann mir nicht vorstellen dass das unter Linux funzt und unter Windows nicht...MSDN Suche hat auch nix ergeben...

So, lange Rede kurzer Sinn...ich wäre sehr froh wenn mir da jemand weiterhelfen könnte...solche Probleme nerven brutal weil sie unnötig aufhalten.
Schöne Grüsse,
Yannick
-
Du musst die Funktionsadressen explizit mit GetProcAddress() holen. Mit Headern wird das nicht funktionieren.
-
Hmmm,
hast du denn den Header eingebunden? Du brauchst ja bestimmt irgendwo die Datentypen aus deinem Plugin oder? Ich frage nur mal so, eventuell kannst du den Header ja mal posten, falls du ihn einbindest.
Wenn nicht, naja: Wie Du schon richtig erkannt hast, musst du per LaodLibrary oder LoadLibraryEx deine Dll laden (in Linux hattest du dann ne .so datei oder ??). Mit GetProcAddress musst du dir dann Die Adresse der Funktion holen. Wie du ja sicher weisst, wird durch LoadLibrary die Dll in den Adressraum der Anwendung angebunden. Mit GetProcAddress bestimmst du dann die Adresse dieser Funktion, natürlich machst du das über einen Funktionszeiger. Dabei muss natürlich die Signatur des Zeigers mit der der Funktion übereinstimmen.
Ist das alles gegeben?!
Also es gibt viele Faktoren, du solltest mal ein wenig mehr Fakten posten.
Gruß Sebastian.
P.S. : Klappt LoadLibrary unter Linux? Das ist doch eine WinApi funktion oder???
-
Was nützt mit GetProcAddress wenn ich vom PLUGIN aus etwas aufrufen will? ich rufe die register_init_plugin() Funktion in DllMain() auf. Also im Plugin...und der Header den ich eingebunden hab (plugin.h) gehört zum Hauptprogramm.
Es geht mir nur darum dem Linker zu sagen "ey, pass auf...die referenzen interessieren dich nicht, das ist ein shared object. die referenzen bekommst du sobald du zum programm hinzugelinkt wurdest per LoadLibrary/dlopen whatever". unter linux ging das nur unter windows mag der linker das nicht *sigh*
und...nein, LoadLibrary gibts nicht unter linux, wie denn auch...da gibts dlopen()

-
Entschuldige, ich hatte dich nicht ganz verstanden. Ich kann dir leider nicht weiterhelfen weil ich anscheined nicht genug Wissen habe um dein Problem zu lösen...
-
Und in Linux ging das? Naja dann muss ja in deinem Plugin was nicht stimmen. Mögliche Ursache könnte zum Beispiel sein das du von Klassen erbst, die abstrakt sind oder zum Beispiel irgendwelche methoden nicht defjnierst.
Ohne Code ist das schwierig.
-
Ja, stimmt... ohne Code gehts schwer.

Wobei ich eher denke das es an Projekt/Linker-Einstellungen liegt...nur welche
plugin.cpp
#include <stdio.h> #include "plugin.h" map<LPCSTR, aosPlugin *> g_PluginMap; extern "C" { void register_init_plugin(PLUG_FUNC pFunc) { return; } void register_cleanup_plugin(PLUG_FUNC pFunc) { return; } }; aosPlugin::aosPlugin(LPCSTR plugName) { g_PluginMap[plugName] = this; m_szPluginName = plugName; m_pInitFunc = NULL; m_pCleanupFunc = NULL; } aosPlugin::~aosPlugin() { map<LPCSTR, aosPlugin *>::iterator iter; m_bLoaded = FALSE; iter = g_PluginMap.find(m_szPluginName.c_str()); g_PluginMap.erase(iter); } BOOL aosPlugin::Load(LPCSTR pathName) { #if defined(WIN32) if((m_hPluginHandle = ::LoadLibrary(pathName)) == NULL) { printf("Couldn't load plugin %s", pathName); return FALSE; } #else if((m_hPluginHandle = ::dlopen(pathName)) == NULL) { printf("Couldn't load module %s", pathName); return FALSE; } #endif m_bLoaded = TRUE; return TRUE; } void aosPlugin::Unload() { #if defined(WIN32) ::FreeLibrary(m_hPluginHandle); #else ::dlclose(m_hPluginHandle); #endif } BOOL aosPlugin::IsLoaded() { if(m_bLoaded) return TRUE; return FALSE; }plugin.h
#ifndef _PLUGIN_H #define _PLUGIN_H #include <map> #include "global.h" extern "C" { #if defined(LINUX) # include <dlfcn.h> #endif }; using namespace std; typedef int(*PLUG_FUNC)(void); extern "C" { void register_init_plugin(PLUG_FUNC pFunc); void register_cleanup_plugin(PLUG_FUNC pFunc); }; class aosPlugin { public: aosPlugin(LPCSTR plugName); ~aosPlugin(); BOOL Load(LPCSTR pathName); void Unload(); BOOL IsLoaded(); private: string m_szPluginName; BOOL m_bLoaded; PLUG_FUNC m_pInitFunc; PLUG_FUNC m_pCleanupFunc; #if defined(WIN32) HMODULE m_hPluginHandle; #else void * m_hPluginHandle; #endif }; extern map<LPCSTR, aosPlugin *> g_PluginMap; #endif // !_PLUGIN_Hbinary.cpp (plugincode)
#include <stdio.h> #include "global.h" #include "plugin.h" #include "binary.h" #if defined(WIN32) BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch(ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } register_init_plugin(binary_init); register_cleanup_plugin(binary_cleanup); printf("binary.dll here...\n"); return TRUE; } #else extern "C" { void _init(void) { return; } }; #endif int binary_init() { return 0; } int binary_cleanup() { return 0; }Hoffe, das hilft weiter...
Gruss,
Yannick