Явная ссылка на классы в DLL - PullRequest
0 голосов
/ 22 июня 2009

У меня есть класс, который в данный момент находится в .lib файле:

class __declspec(dllexport) ReportData {
public:
        list<FileData *> ReportFileData;
        list<SupressionData *> ReportSupressionData;

        static char *ClientName;
        static char *DataRecieved;

        std::string GenFileConfTemplate();

        ~ReportData()
        {
                ReportFileData.clear();
                ReportSupressionData.clear();
        }

};

Я могу добавить этот файл lib в свой проект и без проблем создавать экземпляры этого класса. Мой вопрос, как я могу переместить это в DLL и динамически загрузить его, а также создать экземпляры этого класса. То, что я хочу сделать, это переместить некоторые общие функции в эту библиотеку и делиться ею между несколькими проектами.

Я хочу иметь возможность перекомпилировать dll при необходимости, когда будут внесены изменения, и проекты будут использовать самую последнюю версию; на данный момент, используя lib, я должен перекомпилировать каждый проект после того, как перекомпилирую dll, чтобы изменения произошли, и так как изначально была разработана эта система, есть более 100 проектов, которые будут использовать эту lib / dll не хочу перекомпилировать 100 разных проектов каждый раз, когда вносятся изменения.

Итак, пожалуйста, дайте мне свое экспертное мнение о том, как мне поступить.

Я буду использовать dll внутри моих проектов примерно так:

    ReportData *rd = new ReportData();

    ReportData::ClientName = "test";

    rd->ReportFileData.push_back(new  FileData("testing", 10, 1));
    rd->ReportFileData.push_back(new  FileData("testing 2", 20, 1));

    std::cout << rd->GenFileConfTemplate();

    delete rd;

У меня получилось что-то вроде этого:

typedef Foo* (__stdcall *CreateFunc)();

int main()
{
        HMODULE dll (LoadLibrary ("..\\LLFileConfirmDLL\\LLFileConfirmDLL.dll"));
        if (!dll) {
                cerr << "LoadLibrary: Failed!" << endl;
                std::cin.get();
                return 1;
        }

        CreateFunc create (reinterpret_cast<CreateFunc>(GetProcAddress (dll, "create")));
        if (!create) {
                cerr << "GetProcAddress: Failed!" << endl;
                std::cin.get();
                return 1;
        }

        Foo *f = create();
        cerr << f->Test();


        FreeLibrary (dll);

        std::cin.get();

        return 0;
}

struct FOOAPI Foo
{
        Foo();
        virtual ~Foo(); 
    virtual int Test();
};

Foo::Foo()
{
}

Foo::~Foo()
{
}

int Foo::Test()
{
        return 5;
}

extern "C" __declspec(dllexport) Foo* __stdcall create()
{
        return new Foo;
}

1 Ответ

2 голосов
/ 22 июня 2009

Вы можете сделать это так, как это делает COM:

  1. Экспорт функции CreateInstance ().
  2. Передача void ** и уникального идентификатора в CreateInstance ().
  3. Используемая DLL-библиотека вызывает LoadLibrary () библиотеки DLL и вызывает CreateInstance ().
  4. CreateInstance () создает новые ReportData и возвращает их в параметре void ** out.

Редактировать:

Что-то вроде:

extern "C"
BOOL CreateObject(REFCLSID rclsid, void** ppv) {
    BOOL success = false;
    *ppv = NULL;
    if (rclsid == CLSID_ReportData) {
        ReportData* report_data = new ReportData();
        if (report_data) {
            *ppv = report_data;
            success = true;
        }
    } else if (...) {
        ... other objects ...
    }
    return success;
}

Конечно, теперь вам нужно беспокоиться о таких вещах, как, например, кто освободит объект, убедитесь, что DLL не выгружена и т. Д.

См. Также DllGetClassObject , DllCanUnloadNow и т. Д.

...