Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
maxon887
12 / 12 / 3
Регистрация: 05.06.2012
Сообщений: 280
#1

Ссылка на экземпляр класса в DLL - C++

25.10.2013, 23:08. Просмотров 612. Ответов 12
Метки нет (Все метки)

Написал маленький каркасик для собственново фреймворка, и проблема возникла когда хотель экспортировать его в DLL. Фреймворк предпологает запуск приложения следующим образом:
C++
1
2
3
4
5
6
7
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE prevInstance,LPSTR cmdLine,int cmdShow)
{
    apl = new Application(hInstance);
    Window w(NULL,L"Wirst Class",L"Example2",WS_OVERLAPPEDWINDOW|WS_VISIBLE,
             0,0,400,400,NULL,NULL);
    return apl->Run();
}
указатель apl описан в файле globals.h как
C++
1
2
class Application;
extern Application* apl;
и имеет реально обьявление в другом файле.
Классы которые должны экспортироваться в либу я пометил как __declspec(dllexport)
А вот что делать с Application* apl незнаю.
при попытки скомпилить пишет:
main.obj:-1: ошибка: LNK2001: unresolved external symbol "class Application * apl" (?apl@@3PAVApplication@@A)
ну и это логично)

Добавлено через 6 часов 34 минуты
Ну что никто не знает как решить проблему? может исходники скинуть?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
25.10.2013, 23:08
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Ссылка на экземпляр класса в DLL (C++):

Создание указателя типа базового класса на экземпляр производного класса - C++
Добрый день! Иногда видел коды, где создавался указатель типа базового класса на объект класса - наследника, для чего это может применяться?

Создать экземпляр класса без явного указания членов класса - C++
Если у меня есть два конструктора, один из которых по умолчанию, а второй явный. Я почему-то не могу создать экземпляр класса без явного...

Как построить экземпляр дочернего класса на основе готового экземпляра базового класса? - C++
Если уже есть готовый объект базового класса. Могу я построить экземпляр дочернего на его основе, (напр., получив такой базовый объект...

Создание статической функции класса, которая принимает экземпляр этого же класса как объект - C++
Привет. Есть такой код class Model { public: Model(); Model(int verticesSize, int facesSize); ~Model(); static void...

Вызов методов класса из двойного указателя на экземпляр класса - C++
Добрый день! Как можно вызвать метод класса по двойному указателя на его экземпляр? struct Point { void getPoint(){}; ...

Обращение к методам класса через указатель на экземпляр класса - C++
Добрый день. Не могу осилить проблему: Описан абстрактный класс. Описаны наследники этого класса уже без абстрактности. Описан...

12
Avazart
Нарушитель
Эксперт С++
7232 / 5404 / 293
Регистрация: 10.12.2010
Сообщений: 23,951
Записей в блоге: 17
25.10.2013, 23:11 #2
Цитата Сообщение от maxon887 Посмотреть сообщение
может исходники скинуть?
Вероятно стоит..

А вообще классы в dll это как по мне не очень идея.
1
maxon887
12 / 12 / 3
Регистрация: 05.06.2012
Сообщений: 280
25.10.2013, 23:24  [ТС] #3
Правда тут ещё WinAPI много, так я незнал куда тему создавать.
Класс Application служит для загрузки основного цикла приложения и для получения сообшений от винды.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//application.h
#ifndef APPLICATION_H
#define APPLICATION_H
#include <Windows.h>
#include "window.h"
class __declspec(dllexport) Application
{
public:
    Application(HINSTANCE hInstance);
    LRESULT Run();
    HINSTANCE GetInstance();
protected:
    HINSTANCE hInstance;
};
 
#endif // APPLICATION_H
 
//application.cpp
#include "application.h"
__declspec(dllexport) Application* apl = NULL;
Application::Application(HINSTANCE hInstance)
{
    this->hInstance = hInstance;
}
 
LRESULT Application::Run()
{
    MSG msg;
    while(GetMessage(&msg,NULL,0,0))
    {
        if(msg.hwnd==NULL)
            continue;
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
 
HINSTANCE Application::GetInstance()
{
    return hInstance;
}
Класс Window служит для создания объекта окна, и далешь будет развиваться в сторону абстракного класса
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//window.h
#ifndef WINDOW_H
#define WINDOW_H
#include "application.h"
#include "globals.h"
class __declspec(dllexport) Window
{
public:
    Window(DWORD dwExStyle,LPCTSTR lpszClassName,LPCTSTR lpszWindowName,DWORD dwStyle,
            int x,int y,int nWidth,int nHeight,HWND hwndParent,HMENU nIDorHMenu);
    static Window* FindWindow(HWND hWnd);
    static LRESULT CALLBACK WinProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
    ~Window();
protected:
    HWND hWnd;
};
 
#endif // WINDOW_H
 
//window.cpp
#include "window.h"
#include <vector>
using namespace std;
vector<Window*> LIST;
Window::Window(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName,
               DWORD dwStyle, int x, int y, int nWidth, int nHeight,
               HWND hwndParent, HMENU nIDorHMenu)
{
    LIST.push_back(this);
    hWnd = NULL;
    WNDCLASSEX win;
    win.cbSize = sizeof(WNDCLASSEX);
    win.style = CS_VREDRAW|CS_HREDRAW|CS_OWNDC|CS_DBLCLKS;
    win.lpfnWndProc = Window::WinProc;
    win.cbClsExtra = 0;
    win.cbWndExtra = 0;
    win.hInstance = apl->GetInstance();
    win.hIcon = LoadIcon(NULL,IDI_APPLICATION);
    win.hIconSm = LoadIcon(NULL,IDI_APPLICATION);
    win.hCursor = LoadCursor(NULL,IDC_ARROW);
    win.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    win.lpszMenuName = NULL;
    win.lpszClassName = lpszClassName;
    RegisterClassEx(&win);
    hWnd = CreateWindowEx(NULL,lpszClassName,lpszWindowName,
                          WS_OVERLAPPEDWINDOW|WS_VISIBLE,
                          x,y,nWidth,nHeight,NULL,NULL,apl->GetInstance(),NULL);
 
}
 
Window *Window::FindWindowW(HWND hWnd)
{
    if(hWnd)
    {
        Window* current;
        for(int i = 0; i<LIST.size();i++)
        {
           current = LIST[i];
           if(current->hWnd == hWnd)
               return current;
        }
    }
    return NULL;
}
 
LPARAM Window::WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
    case WM_CREATE:
    {
        break;
    }
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd,&ps);
        //перерисовка окна
        EndPaint(hWnd,&ps);
        break;
    }
    case WM_DESTROY:
    {
        Window* current = FindWindow(hWnd);
        for(int i = 0; i<LIST.size();i++)
        {
            if(LIST[i] == current)
            {
                LIST.erase(LIST.begin()+i);
            }
        }
        if(LIST.size() == 0)
            PostQuitMessage(0);
        return 0;
    }
    default:
        break;
    }
    return(DefWindowProc(hWnd,msg,wParam,lParam));
}
 
Window::~Window()
{
}
//global.h - обьявление глобальных переменных
C++
1
2
3
4
5
6
7
8
9
10
#ifndef GLOBALS_H
#define GLOBALS_H
#include <Windows.h>
#include <vector>
using namespace std;
class Application;
class Window;
extern Application* apl;
extern vector<Window*> LIST;
#endif // GLOBALS_H
Добавлено через 4 минуты
Цитата Сообщение от Avazart Посмотреть сообщение
Вероятно стоит..

А вообще классы в dll это как по мне не очень идея.
Просветите меня пожалуйста
0
Avazart
Нарушитель
Эксперт С++
7232 / 5404 / 293
Регистрация: 10.12.2010
Сообщений: 23,951
Записей в блоге: 17
25.10.2013, 23:27 #4
Цитата Сообщение от maxon887 Посмотреть сообщение
Просветите меня пожалуйста
Ну как бы сможешь использовать dll только под VC++, а под другими комипиляторами нет.

Поэтому смысл? Почему сразу не распространять либу исходниками ?
1
ValeryS
Модератор
6679 / 5088 / 475
Регистрация: 14.02.2011
Сообщений: 17,070
25.10.2013, 23:29 #5
Цитата Сообщение от maxon887 Посмотреть сообщение
Просветите меня пожалуйста
пожалуйста
классы используются в плюсах, а там есть искажение имен
выдергивать из библиотеки не удобно
если использовать Си стиль то классов не будет
1
Avazart
Нарушитель
Эксперт С++
7232 / 5404 / 293
Регистрация: 10.12.2010
Сообщений: 23,951
Записей в блоге: 17
25.10.2013, 23:32 #6
C++
1
2
Window w( NULL,L"Wirst Class",L"Example2",
                       WS_OVERLAPPEDWINDOW|WS_VISIBLE, 0,0,400,400,NULL,NULL);

Не по теме:

Вас такая запись не пугает ?
Нет, тогда зачем вообще было "обворачивать" ?

Ну а вообще идея создать свой фреймворк очень интересна на мой взгляд.

1
ValeryS
Модератор
6679 / 5088 / 475
Регистрация: 14.02.2011
Сообщений: 17,070
25.10.2013, 23:38 #7
если хочешь использовать классы в дллке необходим интерфейс
вот тут так поверхностно рассматривается этот вопрос
http://www.xserver.ru/computer/langprogr/c_c2p/12/
1
maxon887
12 / 12 / 3
Регистрация: 05.06.2012
Сообщений: 280
26.10.2013, 00:42  [ТС] #8
ну ладно, проблемма с классами не самая актуальная, первая проблема в том что Application* apl; не видно из вне библиотеки.
0
Avazart
Нарушитель
Эксперт С++
7232 / 5404 / 293
Регистрация: 10.12.2010
Сообщений: 23,951
Записей в блоге: 17
26.10.2013, 00:52 #9
C++
1
__declspec(dllexport) Application* apl = NULL;
А что это вообще ? Зачем "оно" в хедере?

Цитата Сообщение от maxon887 Посмотреть сообщение
C++
1
apl = new Application(hInstance);
Почему не по нормальному :
C++
1
Application app(hInstance);

Не по теме:

Application по логике должен реализовывать паттерн синглетон.

1
maxon887
12 / 12 / 3
Регистрация: 05.06.2012
Сообщений: 280
26.10.2013, 01:08  [ТС] #10
Цитата Сообщение от Avazart Посмотреть сообщение
А что это вообще ? Зачем "оно" в хедере?
это инициализация ссылки на на обект "приложение". Оно не в хедере а в исходнике. В хедере только
C++
1
extern Application* apl;
оно не по нормальному, потому что остальная часть кода ссылаеться на методы экземпляра класса приложения. Кторый существует как токавой только уже в ран-тайме

Добавлено через 1 минуту
за __delcspec(dllexport) извиняю, эксперементировал. Изначально было просто
C++
1
Application* apl = NULL;
0
Avazart
Нарушитель
Эксперт С++
7232 / 5404 / 293
Регистрация: 10.12.2010
Сообщений: 23,951
Записей в блоге: 17
26.10.2013, 01:19 #11
Почему не сделать к подобно тому как сделано в VCL :
C++
1
Application->CreateForm( ... );
Подобным образом "окно" будет создаваться и сразу передаваться "приложению"
Или передавать в конструктор "окна" объект приложения.

C++
1
2
Application app;
Window w(app);
Добавлено через 7 минут
Цитата Сообщение от maxon887 Посмотреть сообщение
оно не по нормальному, потому что остальная часть кода ссылаеться на методы экземпляра класса приложения. Кторый существует как токавой только уже в ран-тайме
Ну я и говорю не по нормальному...
Разве "окно" должно знать о "приложении" ?
1
maxon887
12 / 12 / 3
Регистрация: 05.06.2012
Сообщений: 280
26.10.2013, 01:44  [ТС] #12
Avazart, два представленных варианта не рассматриваються потому, что на уровне интерфейсов приложение и окна не должны ничего знать друг, о друге. Я думаю понятно почему.
Кстати как то странно ведут себя ссылки в либе, допустим следующи код падает во время выполнения
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//dynamiclib.h
#ifndef DYNAMICLIB_H
#define DYNAMICLIB_H
 
__declspec(dllexport) int exportValue;
__declspec(dllexport) int* link;
#include <iostream>
using namespace std;
 
class __declspec(dllexport) DynamicLib {
public:
    DynamicLib();
    static void Hello();
};
 
#endif // DYNAMICLIB_H
 
//dynamiclib.cpp
#include "dynamiclib.h"
 
 
DynamicLib::DynamicLib()
{
    exportValue = 10;
    link = &exportValue;
}
 
void DynamicLib::Hello()
{
    cout<<"Hello from DLL "<<*link<<endl;
}
Вызов из вне
C++
1
2
3
4
5
6
7
8
9
#include <iostream>
using namespace std;
#include "dynamiclib.h"
int main()
{
    cout << "Hello World!" << endl;
    DynamicLib::Hello();
    return 0;
}
Добавлено через 8 минут
Оо нащёл на msdn
You cannot initialize a static data pointer with the address of a data object declared with the dllimport attribute.
0
maxon887
12 / 12 / 3
Регистрация: 05.06.2012
Сообщений: 280
27.10.2013, 18:18  [ТС] #13
Проблемо была в том что, глобальные переменные либы нельзя менять влоб, тоесть если переменная
C++
1
__declspec(dllexport) extern int i;
то из испольняемого модуля можно только её считать(по крайней мере я незнаю как изменять её не из функций)
сделал следующие в конструкторе Application.
C++
1
2
    delete apl;
    apl = this;
теперь всё работе + ещё круче стало))) теперь это как бы синглетон))

Добавлено через 2 минуты
напоминаю что рание запус фреймворка подразумевал
C++
1
apl = new Application(HINSTANCE);
теперь
C++
1
Application *apl = new Application(HINSTANCE);
0
27.10.2013, 18:18
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.10.2013, 18:18
Привет! Вот еще темы с ответами:

Как сделать членом класса экземпляр этого же класса - C++
class Operation { public: bool type; //true = operation, false = number char Operator; Operation L_Op; Operation R_Op; ...

Может ли метод класса возвращать экземпляр этого же класса? - C++
такой вопрос, реально что бы функция класса имела тип класса(возвращала класс), то есть типа так: class c1{ c1 f1(); } если да, то...

Создать экземпляр класса по ссылке экземпляра класса - C++
Есть класс для обработки клиентов // Абстрактный class ClientProcessing { }; Я создаю от него наследника class...

Классы и объекты в С++, компонента класса и экземпляр класса - C++
Вариант 8. ИЗДЕЛИЕ наименование– char* шифр– char* тип упаковки– char* количество– int 1. Определить пользовательский ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru