Как я могу импортировать DLL класса C ++ внутри пространства имен - PullRequest
5 голосов
/ 15 февраля 2012

Я прочитал некоторые документы, в которых приведены простые примеры функций, совместимых с C.

__declspec(dllexport) MyFunction();

Я согласен с этим. Я пишу небольшое приложение, использующее функции этой библиотеки. Я использовал явное связывание с

LoadLibrary() 

функция. Функции в стиле C работают без проблем. Но когда я пишу свой класс как

namespace DllTest
{
class Test
{
public:
    __declspec(dllexport) Test();
    __declspec(dllexport) void Function( int );
    __declspec(dllexport) int getBar(void);
private:
    int bar;
};

}
#endif

хорошо компилируется и создается Dll. При работе с функциями стиля C я просто брал указатель на функцию из функций LoadLibrary () и GetProcAddress (...).

Мое предыдущее использование

typedef void (*Function)(int);

int main()
{
   Function _Function;
   HINSTANCE hInstLibrary = LoadLibrary(TEXT("test.dll"));

   if (hInstLibrary)
   {
      _Function = (Function)GetProcAddress(hInstLibrary,"Function");
     if (_Function)
     {
        // use the function

Но теперь я понятия не имею, как я могу создать свой класс? Как я могу использовать явную связь или неявную связь?

Буду признателен за любую помощь с примером кода.

Ответы [ 2 ]

6 голосов
/ 15 февраля 2012

Если вы пытаетесь создать экземпляр класса, вам нужно знать его структуру во время компиляции. Вы можете достичь этого, создав абстрактный класс, который определяет методы экземпляра, которые импортированный класс должен будет переопределить. Например:

//interface.h

class TestInterface
{
public:
     virtual void Function( int ) = 0;
     virtual int getBar(void) = 0;
};

Впоследствии в вашей DLL вы можете включить interface.h, унаследовать TestInterface и переопределить чисто виртуальные методы:

//test.h
namespace DllTest {
    class Test : public TestInterface
    {
    public:
         Test();
         void Function( int );
         int getBar(void);
    private:
        int bar;
    };
};

Затем вы можете определить функцию в вашей DLL, которая выделяет объект Test:

extern "C" __declspec(dllexport) TestInterface *allocate_test() {
    return new DllTest::Test();
}

И наконец, когда вы импортируете DLL, найдите символ «allocate_test» и используйте его:

TestInterface *(*test_fun)() = (TestInterface *(*test_fun)())GetProcAddress(hInstLibrary,"allocate_test");
TestInterface *test_ptr = test_fun();
test_ptr->Function(12); //use you object
2 голосов
/ 15 февраля 2012

Во-первых, обратите внимание, что это особенность Microsoft.Для других систем будут действовать другие правила.

Написание того, что вы делали, не работает или, по крайней мере, болезненно.Вам нужно использовать __declspec(dllexport) в DLL, которая определяет функции, но __declspec(dllimport) при компиляции кода, который вызывает функции из другой DLL.Обычный способ справиться с этим - использовать какое-то конкретное имя макроса, указывающее DLL, и сделать что-то вроде:

#ifdef __WIN32
#ifdef MYMODULE_DLL
#define MYMODULE_EXPORT __declspec(dllexport)
#else
#define MYMODULE_EXPORT __declspec(dllimport)
#endif
#else
#define MYMODULE_EXPORT
#endif

Поместите это в заголовок, который включен во все заголовки вашей DLL, и определитеMYMODULE_DLL в командной строке проекта.

Кроме того, можно экспортировать целый класс:

class MYMODULE_EXPORT DllTest
{
    //  ...
};

Это позволяет экспортировать или импортировать все функции и статические данные.Члены класса.

...