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

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

25.10.2013, 23:08. Показов 1525. Ответов 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
8484 / 6151 / 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
8484 / 6151 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
25.10.2013, 23:27
Цитата Сообщение от maxon887 Посмотреть сообщение
Просветите меня пожалуйста
Ну как бы сможешь использовать dll только под VC++, а под другими комипиляторами нет.

Поэтому смысл? Почему сразу не распространять либу исходниками ?
1
Модератор
Эксперт по электронике
8978 / 6744 / 921
Регистрация: 14.02.2011
Сообщений: 23,854
25.10.2013, 23:29
Цитата Сообщение от maxon887 Посмотреть сообщение
Просветите меня пожалуйста
пожалуйста
классы используются в плюсах, а там есть искажение имен
выдергивать из библиотеки не удобно
если использовать Си стиль то классов не будет
1
Эксперт С++
 Аватар для Avazart
8484 / 6151 / 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
Модератор
Эксперт по электронике
8978 / 6744 / 921
Регистрация: 14.02.2011
Сообщений: 23,854
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
8484 / 6151 / 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
8484 / 6151 / 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
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru