Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.82/50: Рейтинг темы: голосов - 50, средняя оценка - 4.82
 Аватар для voalex
32 / 32 / 8
Регистрация: 21.10.2009
Сообщений: 97

Подключение dll содержащей класс

21.10.2009, 11:37. Показов 10513. Ответов 7
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте. У меня возникла проблема с динамическом подключении dll содержащей класс.
#include <windows.h>

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
#define MAX_WIN_PORT 255
 
struct Port
{
    unsigned char Id;    
    bool Availbl;
};
 
struct PortInfo
{
    Port p[MAX_WIN_PORT];
    unsigned char koll;
};
 
 
extern "C" class __declspec (dllexport)  SerialGate
{    
public:
    
    enum IN_LINES_NAME {CTS, DSR, RING, RLSD};
    enum OUT_LINES_NAME {DTR, RTS};    
 
    SerialGate();
    ~SerialGate();    
 
    bool Open(int port, int baud);    
    int Send(char* buff, int szBuff);
    int Recv(char* buff, int szBuff);    
    void SetLine(OUT_LINES_NAME ln, bool state);
    bool GetLine(IN_LINES_NAME ln);
    void GetPortsInfo(PortInfo* pi);
    void Close();
    void Clean();
 
private:
    HANDLE m_hFile;
    bool state;
};
Это необходимо для работы с ком портом. Я знаю как подключить функцию из dll, но как подключить класс я не знаю. Конкретно - что нужно писать в заголовочном файле? Ну я написал
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class TForm1 : public TForm
{
__published:    // IDE-managed Components
        TButton *Button1;
        TButton *Button2;
        TButton *Button3;
        void __fastcall Button1Click(TObject *Sender);
        void __fastcall Button2Click(TObject *Sender);
private:    // User declarations
 
HINSTANCE dllInstance;
 
typedef class(__import * FClass);
 
FClass * DClass;
 
public:        // User declarations
        __fastcall TForm1(TComponent* Owner);
};
- разумеется ругается((
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
21.10.2009, 11:37
Ответы с готовыми решениями:

Подключение dll
У меня подключены dll через lib, они находятся в другой папке и в проекте я подключил ее в настройках, в компиляторе все работает, а при...

Динамическое подключение dll
Здравствуйте! Обращаюсь за помощью к знающим людям! Объясните пожалуйста как динамически подключить dll с помощью LoadLibrary() и...

Подключение библиотек DLL
как в борланде подключить dll библиотеку?

7
1 / 1 / 0
Регистрация: 10.11.2009
Сообщений: 10
11.11.2009, 17:54
Если вопрос ещё актуален, могу поискать сорцы, которые писал, когда столкнулся с таким же вопросом.
0
 Аватар для voalex
32 / 32 / 8
Регистрация: 21.10.2009
Сообщений: 97
12.11.2009, 09:30  [ТС]
Да! Было бы здорово!
0
1 / 1 / 0
Регистрация: 10.11.2009
Сообщений: 10
12.11.2009, 10:57
Сорри! Внимательно прочитал вопрос:
...проблема с динамическом подключении dll содержащей класс...
Есть маленький примерчик импорта класса из DLL неявной компоновкой. А вот при динамическом подключении см. внизу здесь
0
 Аватар для nacgull
1 / 1 / 0
Регистрация: 08.12.2009
Сообщений: 11
09.12.2009, 14:07
//-----------------30 october ...08 december 2009---------------
/*
Мне удалось, на мой взгляд, разработать методику простого ПОЛНОГО явного (динамического) импорта класса из DLL в клиентскую часть, т.е. в EXE или DLL . Во всяком случае для простого использования я уже применил её, далее планирую протестировать для разного использования классов по мере моего, более глубокого, изучения классов C++ и работы с ними.
Предлагаю оценить разработку.

Суть в следующем:
1.Экспортируем через extern "C"__declspec(dllexport), для каждого экспортного класса в DLL, специальную функцию импорта, тело функции (без определения в хедере) помещаем в кодовую часть исходника DLL сразу же за телами методов класса. Внутри тела функции создаем указатель на временный объект в "куче", возвращаем его через return в вызвавший эту функцию импортирующий клиент.

2.Hader DLL с определением экспортируемого класса включаем в исходники кода (DLL и EXE) клиента и сервера(#include "dllmain.h"). Загружаем в клиенте, как обычно при динамическом импорте, файл DLL через

HMODULE lib = LoadLibrary("dllproject.dll");

Вызываем нашу специальную функцию импорта объекта, получаем указатель с адресом на место даных объекта, создаем новый указатель-объект нужного класса и присваиваем объекту адрес с возвращенного указателя. Обращаемся как обычно к переменным-членам этого объекта.
Все разрешенные переменные-члены этого класса уже у нас "в кармане".

3.В hader-е DLL, в определении экспортируемого класса, для каждого экспортируемого метода пишем определение переменной-члена - указателя на этот метод. Внутри тела нашей специальной функции импорта в DLL присваиваем адрес метода класса соответствующему указателю на метод класса как переменной.

TempObjAdress->iMyMethod = &CMyClassB::MyMethod;

Теперь можно обращаться, после сделаного в п.2, к этой переменной и получать адрес кода нужного метода класса. Через него и вызываем метод - получаем "весь мир в кармане" .

(TestObject->*(TestObject.iMyMethod))(argX1, argX2, ... );

4.Остальные наработки упрощают получение кода импорта класса, для получения большого количества методов одного класса наиболее просто работать с макросами.
*/
Привожу пример кода для C++ Builder 2010
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
//========= EXPORT and IMPORT CLASS from/to DLL ===========
// dllproject.dll dllmain.cpp
 
#include <vcl.h>
#include <windows.h>
#pragma hdrstop
#include "dllmain.h"
#pragma argsused
//------------------------------------------------
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
    return 1;
}
//---------------------------------------------------------
CMyClassB::CMyClassB()
{
    a = 1.0f;
    b = 1700;
}
int CMyClassB::MySumB(int Period)
{
//помещаем файл "A.wav" в папку "Debug" этого проекта С++
    PlaySound("A.wav", 0, SND_FILENAME);
    Beep(1500,Period);
    Beep(Period,500);
    return (int)(a+b);
}
int CMyClassB::MySumB2(int Ton)
{
//помещаем файл "Walk-Talk.wav" в папку "Debug" этого проекта С++
    PlaySound("Walk-Talk.wav", 0, SND_FILENAME);
    Beep(b,300);
    Beep(Ton,b);
    return (int)(a+b);
}
//////////////////////////////
ExternDll CMyClassB* CMyClassB_(int InitImport)
{
    CMyClassB* TempObjAdress = new CMyClassB;
// int s = (DataObjAdress->*(DataObjAdress->iMySumB))(100); s = s + s;
 
    if (InitImport)
    {
        TempObjAdress->iMySumB = &CMyClassB::MySumB;
        TempObjAdress->iMySumB2 = &CMyClassB::MySumB2;
    }
// DataObjAdress->iMySumB2 = DataObjAdress->iMySumB;
    return TempObjAdress;
}
//=================================================
//    dllproject.dll        dllmain.h
 
#include <mmsystem.hpp> // for func: PlaySound("FileName", 0, SND_FILENAME);
//----------------------------------------------------------
#define ExternDll extern "C" __declspec(dllexport)
#define ExportDll __declspec(dllexport)
//////////////////////////////////////////////////////////////////////////
/* Универсальные служебные макросы импорта методов класса, помещаем до
 определения экспортируемых классов
*/
// для 3-аргументного метода   Type_Arg1, Type_Arg2, Type_Arg3
#define DLL_METHOD_3(Object_Name, Class_Pointer, Method, Return_Type_Arg, Class_Type, Type_Arg1 )     \
 Return_Type_Arg ( Class_Type ::*Method)( Type_Arg1, Type_Arg2, Type_Arg3 )                             \
     = Object_Name Class_Pointer i ## Method
 
//////////////////////
 
// для 2-х аргументного метода   Type_Arg1, Type_Arg2
#define DLL_METHOD_2(Object_Name, Class_Pointer, Method, Return_Type_Arg, Class_Type, Type_Arg1 )     \
 Return_Type_Arg ( Class_Type ::*Method)( Type_Arg1, Type_Arg2 )                             \
     = Object_Name Class_Pointer i ## Method
 
//////////////////////
 
// для 1-аргументного метода   Type_Arg1
// и для безаргументного метода
#define DLL_METHOD_01(Object_Name, Class_Pointer, Method, Return_Type_Arg, Class_Type, Type_Arg1 )     \
 Return_Type_Arg ( Class_Type ::*Method)( Type_Arg1 )                             \
     = Object_Name Class_Pointer i ## Method
 
///////////////////////////////////////////////////////////////////////////
// определение класса
class CMyClassB
{
CMyClassB_Types
 public:
    // экспортируемые методы
    CMyClassB();
     //DLL Pointer Method Export-Import
    void (CMyClassB::*iCMyClassB)();
 
    int MySumB(int);
      //DLL Pointer  Method Export-Import
    int (CMyClassB::*iMySumB)(int);
 
    int MySumB2(int);
    //DLL Pointer Method Export
    int_CMyClassB_int  iMySumB2;
 
    // . . . другие НЕэкспортируемые методы класса
 
    float a; // экспортируемая переменная
    int b;   // экспортируемая переменная
 private:
    int x;   // НЕэкспортируемая переменная
};
//---------------------------------------------------------------------------
/* Для каждого экспортируемого метода каждого экспортируемого класса пишем
  уникальный служебный макрос, помещаем после определения класса
*/
#define DLL_METHODS_CMyClassB( Object_Name, Class_Pointer )                         \
/*                   NameFuncCreateObject   Class_Type_    Class_Type_Ptr         */  \
/*                            TypePointer   &                *                      */  \
/*                            Class_Pointer .                ->                    */  \
DLL_METHOD_01( Object_Name, Class_Pointer, MySumB,  int, CMyClassB, int ) ;        \
DLL_METHOD_01( Object_Name, Class_Pointer, MySumB2, int, CMyClassB, int ) ;       \
//DLL_METHOD_01( Object_Name, Class_Pointer, CMyClassB, void, CMyClassB,  ) ;
 
///////////////////////////////////////////////////////////////////////////////
/*        Универсальные макросы     */
 
//1.  Универсальный служебный макрос, помещаем в конце страницы
#define DLL_IMPORT_CLASS( Library_Name, Class_Type)                                    \
/*                 NameFuncCreateObject   Class_Type_    Class_Type_Ptr         */  \
/*                                TypePointer   &                *                      */  \
/*                            Class_Pointer .                ->                    */  \
 Class_Type & (*  Class_Type ## _ )(int) ;                              \
 Class_Type ## _ = ( Class_Type & (*)(int))GetProcAddress(Library_Name, "_" #Class_Type  "_" );  \
                 \
 \
 Class_Type * (*  Class_Type ## _ ## Ptr )(int) ;                              \
 Class_Type ## _ ## Ptr = ( Class_Type * (*)(int))GetProcAddress(Library_Name, "_" #Class_Type  "_" );  \
 
////////////////////////////////////
//2. Универсальные пользовательские макросы, помещаем в конце страницы
 
/* - для создания объекта импортируемого из сервера (из DLL в EXE например)
 класса, используем, если здесь объекты даного класса уже создавались
*/
#define DLL_CREATE_DATABLOCK( Class_Type, Object_Name )                                     \
Class_Type & Object_Name =  Class_Type ## _ ## (0) ; /* 0 ~ без инициализации указателей на методы класса */
 
/* - для создания указателя объекта импортируемого из сервера
 класса, используем, если здесь объекты даного класса уже создавались
*/
#define DLL_CREATE_POINTER( Class_Type, Object_Name )                                     \
Class_Type * Object_Name =  Class_Type ## _ ## Ptr ## (0) ; /* 0 ~ без инициализации указателей на методы класса */
 
////////////////////////////////////
//3. Универсальные пользовательские макросы, помещаем в конце страницы
 
/* - для создания объекта импортируемого из сервера
 класса, используем, если здесь объекты даного класса еще не создавались
*/
#define DLL_IMPORT_DATABLOCK( Library_Name, Class_Type, Object_Name)  \
DLL_IMPORT_CLASS( Library_Name, Class_Type)  ;                                   \
Class_Type & Object_Name =  Class_Type ## _ ## (1) ; /* 1 ~ инициализация указателей на методы класса */ \
DLL_METHODS_ ## Class_Type ## ( Object_Name, . )
 
/* - для создания указателя объекта импортируемого из сервера
 класса, используем, если здесь объекты даного класса еще не создавались
*/
#define DLL_IMPORT_POINTER( Library_Name, Class_Type, Object_Name)    \
DLL_IMPORT_CLASS( Library_Name, Class_Type) ;                                    \
Class_Type * Object_Name =  Class_Type ## _ ## Ptr ## (1) ; /* 1 ~ инициализация указателей на методы класса */    \
DLL_METHODS_ ## Class_Type ## ( Object_Name, -> )
 
//==============================================================================
//    appmain.exe        Unit1.cpp
#include <vcl.h>
#include <stdio.h>
#include <conio.h>
#pragma hdrstop
#include "dllmain.h"
#include "Unit1.h"
 
#pragma package(smart_init)
#pragma resource "*.dfm"
//---------------------------------------------------------------------------
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
 
void __fastcall TForm1::Button10Click(TObject *Sender)
{
HMODULE lib = LoadLibrary("dllproject.dll"); //стандартная загрузка DLL в память
//////////////////////////
/* Простой быстрый импорт класса с созданием указателя объекта Test и указателя
 на метод
*/
// CMyClassB* Test = ((CMyClassB* (*)())GetProcAddress(lib, "_CMyClassB_"))();
//    int (CMyClassB::*MySumB2)(int) = Test->iMySumB2;
///////////////////////////////////////
 
//Полный импорт класса и первоначальное создание указателя объекта с помощью макроса
DLL_IMPORT_POINTER( lib, CMyClassB, Test) ; //DLL_IMPORT_POINTER( Library_Name, Class_Type, Object_Name)
 
/*вызываем метод из DLL через дополнительный указатель, совпадающим с именем
      дополнителного указателя
*/
      (Test->*MySumB2)(700);
 
// обращение к переменной из DLL
     // Test->a = Test->a + Test->b;
        Test->b = 250;
// создаем другой указатель объекта уже импортированного класса
DLL_CREATE_POINTER( CMyClassB, Test1 )  ; //DLL_CREATE_POINTER( Class_Type, Object_Name )
 
/*вызываем метод из DLL через дополнительный указатель, совпадающим с именем
      дополнителного указателя
*/
      (Test1->*MySumB2)(400);
 
        Test1->b = 450;
// создаем еще один объект (безуказательный)  уже импортированного класса
DLL_CREATE_DATABLOCK( CMyClassB, Test2 )  //
 
/*вызываем метод из DLL через дополнительный указатель, совпадающим с именем
      дополнителного указателя
*/
      (Test2.*MySumB2)(400);
        Test2.b = 450;
//////////////////////////////////////////
// Простой быстрый импорт класса с созданием объекта Mest
CMyClassB& Mest = ((CMyClassB& (*)())GetProcAddress(lib, "_CMyClassB_"))();
/* эквивалентно
    CMyClass& Mest = (  (CMyClassB& (*)()  )GetProcAddress(lib, "_CMyClassB_");
    Mest = CMyClassB_();
*/
//    можно присвоить еще один дополнительный указатель на метод класса DLL
//    int (CMyClassB::*MMySumB2)(int) = Mest->iMySumB2;
//      (Mest.*MMySumB2)(500);
 
      (Mest.*MySumB2)(500);
                              (Test->*MySumB2)(700);
      Mest.a = Mest.a + Mest.b;
 
      //delete[] &Test;  // ... удаляем, если надо очистить пространство :)))
 
    FreeLibrary(lib); lib = NULL; // стандартная выгрузка DLL из памяти
}
 
//=============================================================================
//  appmain.exe     Unit1.h
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
 
#ifndef Unit1
#define Unit1
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
 
//          . . .  определения
0
1 / 1 / 0
Регистрация: 10.11.2009
Сообщений: 10
09.12.2009, 15:02
nacgull, может я не по теме, но разве правильно возвращать из функции указатель на объект созданнй в куче? Ведь теперь становиться важно, чтоб вызывающая программа корректно удаляла этот объект. Не будет ли утечка ресурсов? В Вашем примере проскакивал delete и тот закоментирован.
0
 Аватар для nacgull
1 / 1 / 0
Регистрация: 08.12.2009
Сообщений: 11
10.12.2009, 10:46
Цитата Сообщение от Smile_Yo Посмотреть сообщение
nacgull, может я не по теме, но разве правильно возвращать из функции указатель на объект созданнй в куче? Ведь теперь становиться важно, чтоб вызывающая программа корректно удаляла этот объект. Не будет ли утечка ресурсов? В Вашем примере проскакивал delete и тот закоментирован.
По теме . Я еще только начал более глубоко изучать С++ , поэтому еще обдумываю эту проблемку. Не во всех, но в некоторых, случаях этого примера мой C++ Builder 2010 выдавал ошибку компиляции. В начале статьи указано, что я планирую более глубоко тестировать этот способ, а также это только ПРИМЕРНЫЙ код - думаю это всё объясняет. Мне главное было выложить идею.

И еще, в случае некоторых исключений c обработкой на "куче" (catch) во время возврата из создающей функции импорта, может возникнуть "затирание" инициализированых конструктором класса переменных-членов новосозданного экземпляра объекта.

Кроме того, таким способом можно обращаться к методу класса не через указатель типа "метод класса", а через указатель типа "функция" (придется применять дополнительный идентификатор fMySumB):
C++
1
2
3
              Test.b = Test.fMySumB(1234);
//                      и 
              Test->b = Test->fMySumB(1234);
Хотя компилятор ошибки не выдаст, но если в методе класса для возврата использовать "return variable ;" вместо "return 4321" ( тоесть переменнную вместо значения) - операционная система у меняя выдавала ошибку. Это , наверно, из-за разных типов (указатель типа "функция" и указатель типа "метод класса").
0
 Аватар для nacgull
1 / 1 / 0
Регистрация: 08.12.2009
Сообщений: 11
11.12.2009, 13:06
Цитата Сообщение от Smile_Yo Посмотреть сообщение
nacgull, ... важно, чтоб вызывающая программа корректно удаляла этот объект. Не будет ли утечка ресурсов? В Вашем примере проскакивал delete и тот закоментирован.
Немного разобрался: для большей полноты примера вместо закоментированого в сторке 244
C++
1
//delete[] &Test;  // ... удаляем, если надо очистить пространство :)))
я предлагаю поместить такое:
C++
1
delete Test; Test=NULL; delete Test1; Test1=NULL;delete &Test2; delete &Mest; //очистка "кучи" от ненужных обектов и "зануление" указателей для безопасности в случае ошибочного повторного вызова через эти указатели
Оператор new выделяет область памяти и возвращает указатель на её первую ячейку. Оператор delete освобождает память, выделенную ранее с помощью оператора new. При таком коде, в работе откомпилированной программы и DLL ошибок не возникало. Мне осталось убедится в правильности очистки памяти с помощью debuger-a C++ Builder 2010 .

Добавлено через 48 минут
Очень хорошо рассмотрена тема подключения DLL , в частности предлагается динамический импорт класса вот , но он громоздкий и к тому же вызов метода класса ведётся через "указатель-на-функцию" вместо "указатель-на -метод-класса", что не совсем корректно и может повлечь ошибки при работе откомпиллированой программы, а также мешает проблема "искажения" ( mangle ) имен импортируемых функций с аргументами при экспорте без " extern "C" ".

В разных местах Инета предлагаются разные способы динамического импорта методов класса, но они основаны на "указатель-на-функцию". Есть также хороший учебник с разделом о DLL, правда немного устаревший:
Borland C++ Builder in 21 Days. Кент Рейсдорф и Кен Хендерсон, перевод на русский.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
11.12.2009, 13:06
Помогаю со студенческими работами здесь

подключение dll библиотеки
как подключить dll библиотеку в билдер с++ через опции проекта

Подключение сторонней dll к пректу.
Все поиски излазил, задолбался, не найду ничего путного. Есть чужая dll (единственный файл, без lib, h и т.д.) Есть подробное описание...

Подключение к проекту Skype4com.dll
Не знаю как подключать динамические библиотеки к проекту, чтобы потом с ними работать... Подскажите как

Подключение DLL из памяти без сохранения ее на диск
У меня есть DLL которую надо подключить к программе в процессе ее выполнения. Проблема в том что она хранится не на диске а в памяти в виде...

Подключение dll библиотек, построенных на других языках
Возможно ли подключить к проекту на C++ Builder библиотеку, построенную на C#?


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

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru