PluginManager Problem



  • Hallo.

    Ich habe ein Problem.
    Der BCB macht was er will oder ich weiß net was falsch ist.

    Erstmal eine Beschreibung was ich vorhabe.
    Ich möchte in meinem Programm ermöglichen Plugins zu nutzen.

    Ich habe mir vorerst eine Klasse entwickelt die das hand haben soll.

    // Datei: common.h
    #ifndef commonH
    #define commonH
    #include <vcl.h>
    
    typedef struct {
      HINSTANCE   hDLL;
      AnsiString  strPluginFile;
      AnsiString  strPluginName;
      AnsiString  strPluginAuthor;
      AnsiString  strPluginVersion;
    } TPluginInfo;
    
    #endif
    

    Die Klasse TPluginLoader.

    // Datei: TPluginLoader.h
    //---------------------------------------------------------------------------
    
    #ifndef TPluginLoaderH
    #define TPluginLoaderH
    //---------------------------------------------------------------------------
    #include <vcl.h>
    #include <filectrl.hpp>
    #include "..\common.h"
    //---------------------------------------------------------------------------
    typedef TPluginInfo* (*IMPFUNC)();
    
    class TPluginLoader {
    private:
      DynamicArray<TPluginInfo> pPluginData;
      TPluginInfo *pPluginInfo;
      TStrings *pPluginFiles;
    
      AnsiString strPluginFolder;
    
      void ScanAfterPlugins(AnsiString strDirName, AnsiString strWildCards,
                            TStrings *sllFileList, bool blNoExtension);
      bool Load(AnsiString PluginFile);
      bool UnloadPlugin(void);
      bool Get_DLL_Info(HINSTANCE DLL);
    protected:
    public:
      TPluginLoader(AnsiString PluginFolder);
      ~TPluginLoader(void);
      void Scan(void);
    };
    
    //---------------------------------------------------------------------------
    #endif
    
    // Datei: TPluginLoader.cpp
    //---------------------------------------------------------------------------
    
    #pragma hdrstop
    
    #include "TPluginLoader.h"
    
    //---------------------------------------------------------------------------
    
    #pragma package(smart_init)
    
    TPluginLoader::TPluginLoader(AnsiString PluginFolder)
    {
      this->pPluginFiles        = new TStringList();
      this->pPluginData.Length  = 0;
      this->strPluginFolder     = PluginFolder;
    }
    //---------------------------------------------------------------------------
    
    TPluginLoader::~TPluginLoader(void)
    {
      //TODO: Add your source code here
    }
    //---------------------------------------------------------------------------
    
    void TPluginLoader::ScanAfterPlugins(AnsiString strDirName,
                                         AnsiString strWildCards,
                                         TStrings *sllFileList,
                                         bool bNoExtension)
    {
      TSearchRec stlSearchResult;
      AnsiString strEntry;
    
      sllFileList->Clear();
    
      if(sllFileList != NULL && strDirName != EmptyStr && strWildCards != EmptyStr) {
        strDirName  = IncludeTrailingBackslash(strDirName);
    
        try {
          AnsiString strSearchDir = strDirName + strWildCards;
    
          if(FindFirst(strSearchDir,faAnyFile,stlSearchResult) == 0) {
            strEntry  = bNoExtension && stlSearchResult.Name.Length() ?
                        stlSearchResult.Name.SubString(1,stlSearchResult.Name.Length()-
                                                       ExtractFileExt(stlSearchResult.Name).Length()) :
                        stlSearchResult.Name;
    
            sllFileList->Add(strEntry);
    
            while(FindNext(stlSearchResult) == 0) {
              strEntry  = bNoExtension && stlSearchResult.Name.Length() ?
                          stlSearchResult.Name.SubString(1,stlSearchResult.Name.Length()-
                                                        ExtractFileExt(stlSearchResult.Name).Length()) :
                          stlSearchResult.Name;
    
              sllFileList->Add(strEntry);
            } // END OF WHILE
    
            FindClose(stlSearchResult);
          } // END OF if(FindFirst())
        } // END OF try
        catch(...) { ; }
      } // END OF if(sllFileList !=....)
    } // END OF ScanAfter
    //---------------------------------------------------------------------------
    
    void TPluginLoader::Scan(void)
    {
      this->ScanAfterPlugins(this->strPluginFolder,"*.plx",this->pPluginFiles,false);
      ShowMessage("Plugins gefunden: " + AnsiString(this->pPluginFiles->Count));
      for(int iIndex = 0;iIndex < this->pPluginFiles->Count;iIndex++) {
        this->Load(this->pPluginFiles->Strings[iIndex]);
      }
    }
    //---------------------------------------------------------------------------
    
    bool TPluginLoader::Load(AnsiString PluginFile)
    {
      HINSTANCE DllInstance;
    
      PluginFile  = this->strPluginFolder + PluginFile;
    
      ShowMessage("Lade Plugin:\n" + PluginFile);
    
      if(!DllInstance) DllInstance = LoadLibrary(PluginFile.c_str());
    
      if(DllInstance) {
        if(this->Get_DLL_Info(DllInstance)) {
          ShowMessage("Plugin ist richtig...");
    
          return true;
        }
        else { ShowMessage("Plugin ist nicht richtig..."); }
      }
      else { ShowMessage("Plugin wurde nicht geladen. Es ist ein Fehler aufgetreten!!!"); }
    
      return false;
    }
    //---------------------------------------------------------------------------
    
    bool TPluginLoader::UnloadPlugin(void)
    {
      return false;
    }
    //---------------------------------------------------------------------------
    
    bool TPluginLoader::Get_DLL_Info(HINSTANCE DLL)
    {
      IMPFUNC DLLFunktion;
    
      if(this->pPluginInfo != NULL) {
        this->pPluginInfo = NULL;
      }
    
      this->pPluginInfo = new TPluginInfo;
    
      if(DLL) {
        DLLFunktion = (IMPFUNC)GetProcAddress(DLL,"_GetInfo"); // Ich habe es auch mal mit GetInfo probiert.
    
        if(DLLFunktion) {
          /*this->pPluginInfo =*/ DLLFunktion();
    
          return true;
        }
        else {
          return false;
        }
      }
    
      return false;
    }
    

    Im Programm rufe ich einfach die Methode Scan() auf.

    -----------------------------------------------------------

    Nun zu einem Test-Plugin.
    Projekt erstellt mit den Einstellungen:
    C++, VCL.

    Das PluginCode:

    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #include <windows.h>
    #include "..\common.h"
    #pragma hdrstop
    TPluginInfo *PluginInfo;
    
    #pragma argsused
    int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
    {
      switch(reason) {
        case DLL_PROCESS_ATTACH:
        ShowMessage("Die DLL-Datei wurde geladen.");
        break;
    
        //-------------------------------------
    
        case DLL_PROCESS_DETACH:
        ShowMessage("Die DLL-Datei wurde entladen.");
        break;
      }
    
      return 1;
    }
    //---------------------------------------------------------------------------
    
    extern "C" __declspec(dllexport) TPluginInfo* GetInfo() {
      PluginInfo  = new TPluginInfo;
    
      PluginInfo->strPluginName   = "Sound";
      PluginInfo->strPluginVersion  = "1.0.0.0";
      PluginInfo->strPluginAuthor = "DJ BlackEagle";
    
      return PluginInfo;
    }
    

    Jetzt ist die Frage, was ich da falsch mache...

    In der Methode "bool TPluginLoader::Get_DLL_Info(HINSTANCE DLL)"
    wird ja mit GetProcAddress(), die Adresse der Funktion geholt, aber erhalte immer den Wert NULL.



  • Hast du mal in der Schnellansicht nachgesehn, ob GetInfo überhaupt exportiert wird?



  • bzw. mit ImpDef mal die Exportnamen angeschaut?



  • Ich habe es mit einem HexEditor nach geschaut und da gabs ne Funktion namens _GetInfo.

    Ich habe auch mal Impdef gemacht.

    Hier mit der Option -a:

    LIBRARY SOUND.PLX

    EXPORTS
    _GetInfo @1 ; _GetInfo
    ___CPPdebugHook @2 ; ___CPPdebugHook

    Hier mal mit den Optionen -a -h:

    LIBRARY SOUND.PLX

    EXPORTS
    _GetInfo @1 @0 ; _GetInfo
    ___CPPdebugHook @2 @1 ; ___CPPdebugHook

    Und einmal ohne Optionen:

    LIBRARY SOUND.PLX

    EXPORTS
    _GetInfo @1 ; _GetInfo
    ___CPPdebugHook @2 ; ___CPPdebugHook

    Also ist der Aufruf mit GetProcAddress(HINSTANCE,"_GetInfo"); richtig.

    [edit]Achja, LoadLibrary(PluginFile.c_str()); wird erfolgreich ausgeführt...[/edit]



  • Du könnetst mal GetLastError() aufrufen. Evtl steht da noch mehr drin. Ein weiterer Vorschlag ist es mit "GetInfo" statt "_GetInfo" zu probieren, also ohne Unterstrich vor dem Namen.



  • wie der Kommentar im Quellcode steht, habe ich es ohne _ versucht. Aber auch ohne erfolg. An der Endung sollte es ja nicht liegen.

    bool TPluginLoader::Get_DLL_Info(HINSTANCE DLL)
    {
      IMPFUNC DLLFunktion;
    
      if(this->pPluginInfo != NULL) {
        this->pPluginInfo = NULL;
      }
    
      this->pPluginInfo = new TPluginInfo;
    
      if(DLL) {
        DLLFunktion = (IMPFUNC)GetProcAddress(DLL,"_GetInfo");
        LPVOID lpMsgBuf;
        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
                      NULL,
                      GetLastError(),
                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                      (LPTSTR) &lpMsgBuf,
                      0,
                      NULL);
    
        // Display the string.
        MessageBox( NULL, (LPTSTR)lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION );
    
        // Free the buffer.
        LocalFree( lpMsgBuf );
    
        if(DLLFunktion) {
          /*this->pPluginInfo =*/ DLLFunktion();
    
          return true;
        }
        else {
          return false;
        }
      }
    
      return false;
    }
    

    Die MessageBox sagt mir: "Das angegebene Modul wurde nicht gefunden."


Anmelden zum Antworten