Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.86/7: Рейтинг темы: голосов - 7, средняя оценка - 4.86
 Аватар для maxon887
12 / 12 / 7
Регистрация: 05.06.2012
Сообщений: 280

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

25.10.2013, 23:08. Показов 1577. Ответов 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
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
25.10.2013, 23:08
Ответы с готовыми решениями:

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

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

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

12
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
25.10.2013, 23:11
Цитата Сообщение от maxon887 Посмотреть сообщение
может исходники скинуть?
Вероятно стоит..

А вообще классы в dll это как по мне не очень идея.
1
 Аватар для maxon887
12 / 12 / 7
Регистрация: 05.06.2012
Сообщений: 280
25.10.2013, 23:24  [ТС]
Правда тут ещё 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
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
25.10.2013, 23:27
Цитата Сообщение от maxon887 Посмотреть сообщение
Просветите меня пожалуйста
Ну как бы сможешь использовать dll только под VC++, а под другими комипиляторами нет.

Поэтому смысл? Почему сразу не распространять либу исходниками ?
1
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,871
25.10.2013, 23:29
Цитата Сообщение от maxon887 Посмотреть сообщение
Просветите меня пожалуйста
пожалуйста
классы используются в плюсах, а там есть искажение имен
выдергивать из библиотеки не удобно
если использовать Си стиль то классов не будет
1
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
25.10.2013, 23:32
C++
1
2
Window w( NULL,L"Wirst Class",L"Example2",
                       WS_OVERLAPPEDWINDOW|WS_VISIBLE, 0,0,400,400,NULL,NULL);

Не по теме:

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

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

1
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,871
25.10.2013, 23:38
если хочешь использовать классы в дллке необходим интерфейс
вот тут так поверхностно рассматривается этот вопрос
http://www.xserver.ru/computer/langprogr/c_c2p/12/
1
 Аватар для maxon887
12 / 12 / 7
Регистрация: 05.06.2012
Сообщений: 280
26.10.2013, 00:42  [ТС]
ну ладно, проблемма с классами не самая актуальная, первая проблема в том что Application* apl; не видно из вне библиотеки.
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
26.10.2013, 00:52
C++
1
__declspec(dllexport) Application* apl = NULL;
А что это вообще ? Зачем "оно" в хедере?

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

Не по теме:

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

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

Добавлено через 1 минуту
за __delcspec(dllexport) извиняю, эксперементировал. Изначально было просто
C++
1
Application* apl = NULL;
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
26.10.2013, 01:19
Почему не сделать к подобно тому как сделано в VCL :
C++
1
Application->CreateForm( ... );
Подобным образом "окно" будет создаваться и сразу передаваться "приложению"
Или передавать в конструктор "окна" объект приложения.

C++
1
2
Application app;
Window w(app);
Добавлено через 7 минут
Цитата Сообщение от maxon887 Посмотреть сообщение
оно не по нормальному, потому что остальная часть кода ссылаеться на методы экземпляра класса приложения. Кторый существует как токавой только уже в ран-тайме
Ну я и говорю не по нормальному...
Разве "окно" должно знать о "приложении" ?
1
 Аватар для maxon887
12 / 12 / 7
Регистрация: 05.06.2012
Сообщений: 280
26.10.2013, 01:44  [ТС]
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 / 7
Регистрация: 05.06.2012
Сообщений: 280
27.10.2013, 18:18  [ТС]
Проблемо была в том что, глобальные переменные либы нельзя менять влоб, тоесть если переменная
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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
27.10.2013, 18:18
Помогаю со студенческими работами здесь

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru