Tworzenie / użycie obiektu klasy zdefiniowanej w bibliotece DLL

0

Witam.

Nagłówek biblioteki DLL:


#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 */

#include <Windows.h>
#include <iostream>

using namespace std;

class Test 
{
    public:
        int val;

    public:
        Test();
        virtual int non();
                virtual int get();
};

#endif /* _DLL_H_ */

Definicja klasy


#include "DLLClass.h"

Test::Test()
{
    val = 99;
}

int Test::non()
{
    return 555;
}

int Test::get()
{

    return val;
}

extern "C" __declspec(dllexport) Test * CreateObjectOfClass()
{
    return new Test();
}

BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason ,LPVOID reserved)
{
    switch(reason)
    {
        case DLL_PROCESS_ATTACH:
            cout << "Load DLL" << endl;
        break;

        case DLL_PROCESS_DETACH:
            cout << "Unload DLL" << endl;
        break;

        case DLL_THREAD_ATTACH:
        break;

        case DLL_THREAD_DETACH:
        break;
    }

    return TRUE;
}

Wykorzystanie biblioteki:


#include <windows.h>
#include <iostream>
#include <string>
#include "DLLClass.h"

using namespace std;

int main()
{
    HMODULE hMod;
    hMod = LoadLibrary("E:\\DLLClass\\Release\\DLLClass.dll");

    if(hMod != NULL)
    {

        typedef Test* (*PFNCreateTest)();

        PFNCreateTest pfnCreateTest = (PFNCreateTest)GetProcAddress(hMod, "CreateObjectOfClass");

        if(pfnCreateTest != NULL)
        {
            Test * a = (pfnCreateTest)();

            cout << a->get() << endl;

            delete a;

            a = NULL;
        }

        FreeLibrary(hMod);
    }

    return 0;
}

Problem polega na tym, iż każda metoda klasy, która chce wykonywać jakieś operacje na jej składnikach ( w tym wypadku na zmiennej val ), powoduje naruszenie segmentu pamięci. Metoda get zwraca jedynie wartość zmiennej publicznej val. Wygląda na to, że sposób deklaracji metod klasy powoduje, iż nie widzą się one na wzajem. Dzieje się to samo, gdy z funkcji get chciałbym wywołać metodę non.

Obiekt klasy jest tworzony. Potrafię wywołać funkcję non bez błędnie, ale ona nie działa na zmiennej val.

Mogę również bezpośrednio odwołać się do publicznej zmiennej val:

Test * a = (pfnCreateTest)();

 cout << a->val << endl;

Ciekawostką jest jedna rzecz. Otóż modyfikując nieco funkcję get wszystko działa w porządku. Oto kod:


// deklaracja w klasie
virtual int get(Test * ptr);

// definicja
int Test::get(Test * ptr)
{
    return ptr->val;
}

// użycie
Test * a = (pfnCreateTest)();

cout << a->get(a) << endl;

, wtedy wszystko działa w porządku.

Będę wdzięczny za wskazówki.

Pozdrawiam

0

Spróbuj tak:

#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
# define _PURE 
#else 
# define DLLIMPORT __declspec (dllimport)
# define _PURE =0 
#endif 

#include <Windows.h>
#include <iostream>

using namespace std;

class Test 
{
        public:
                int val;

        public:
                Test();
                virtual int non() _PURE;
                virtual int get() _PURE;
};

#endif /* _DLL_H_ */

p.s. jeśli tworzysz coś na stercie po stronie DLL-ki, to zadbaj o to, żeby po tej samej stronie zostało to coś zwolnione.

0

Witam.

Dziękuję za odpowiedź.

Jednak po modyfikacji zasugerowanej przez Ciebie, w funkcji:


extern "C" __declspec(dllexport) Test * CreateObjectOfClass()
{
    return new Test();
}

otrzymuję błąd kompilacji:

DLLClass.cpp(21): error C2259: 'Test' : cannot instantiate abstract class due to following members:
'int Test::non(void)' : is abstract
e:\dllclass\dllclass\DLLClass.h(26) : see declaration of 'Test::non'
'int Test::get(void)' : is abstract
e:\dllclass\dllclass\DLLClass.h(27) : see declaration of 'Test::get'

Próbowałem wcześniej czegoś podobnego, tworząc "interfejs" dla klasy Test :


class Inter
{
       public:
                virtual int non() = 0;
                virtual int get() = 0; 
}

class Test : public Inter
{
        public:
                int val;

        public:
                Test();
                int non();
                int get();
};

, ale niestety nie pomogło.

0

Bo nie masz poprawnie zdefiniowanego BUILDING_DLL (zakładam, że z tego samego nagłówka korzysta aplikacja lub biblioteka, która importuje ów klasę). Zdefiniuj to makro w projekcie DLL-ki, w opcjach.

I nie:

extern "C" __declspec(dllexport) Test * CreateObjectOfClass() { ... } 

tylko

extern "C" DLLIMPORT Test * CreateObjectOfClass(); 
0

Tym razem, po dodaniu makra do opcji projektu, otrzymuję błąd:

e:\dllclass\dllclass\DLLClass.h(26): error C3646: '_PURE' : unknown override specifier
e:\dllclass\dllclass\DLLClass.h(27): error C3646: '_PURE' : unknown override specifier

Zapewne wciąż jest to problem z makrem BUILDING_DLL.

Dodałem je w opcjach projektu DLL-ki, C/C++/Preprocessor/Preprocessor Definitions

0

Dodałem definicję _PURE dla niezdefiniowanego BUILDING_DLL, ale niestety DLL-ka zachowuje się wciąż tak samo - metoda get powoduje błąd.

0

Nie wiem, być może czegoś nie widzę, ale według mnie wszystko powinno być ok. W każdym razie nie spotkałem się z takim zachowaniem tego typu kodu. Czy DLLClass.h to jest ten nagłówek, który zawiera definicję klasy Test? Jeśli tak, to dlaczego nie ma tam deklaracji CreateObjectOfClass? Może pokaż zawartość DLLClass.h.

0

Nagłówek poprawiłem według Twoich wcześniejszych uwag:


#ifndef _DLL_H_
#define _DLL_H_

#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport)
# define _PURE 
#else 
# define DLLIMPORT __declspec (dllimport)
# define _PURE =0 
#endif 

#include <Windows.h>
#include <iostream>

using namespace std;

class Test
{
    public:
        int val;

    public:
        Test();
        virtual int non() _PURE;
        virtual int get() _PURE;
};

extern "C" DLLIMPORT Test * CreateObjectOfClass();

#endif /* _DLL_H_ */
0

A w pliku .cpp od klasy test masz aby zdefiniowaną globalną funkcję createObjectOfClass()?

0

Tak, funkcja jest zdefiniowana w pliku cpp klasy Test:


Test::Test()
{
    val = 99;
}

int Test::non()
{
    return 555;
}

int Test::get()
{
    return val;
}

Test * CreateObjectOfClass()
{
    return new Test();
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0