Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
 Аватар для Argus19
1732 / 476 / 78
Регистрация: 24.09.2017
Сообщений: 2,573
Записей в блоге: 27

Как написать библиотеку на С++ для программ на VB 6.0

19.12.2024, 18:58. Показов 6417. Ответов 58

Студворк — интернет-сервис помощи студентам
Часто разбрасываюсь и забываю о многом. Скомпилировал две статьи из интернета и добавил кое-что своё.
Прошу исправить ошибки, если что-то неправильно описал и дополнить, если что-то упустил. Делал фактически "на скаку".
1
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
19.12.2024, 18:58
Ответы с готовыми решениями:

Написать синтезатор используя библиотеку conio.h для подключения клавиатуры и библиотеку Windows.h для Beep
Написать синтезатор используя библиотеку conio.h для подключения клавиатуры и библиотеку Windows.h для Beep(частота,длительность). ...

Как написать dll библиотеку для lua?
Скажите пожалуйста, как написать dll библиотеку для lua. попробовать так не вышло. // dllmain.cpp : Определяет точку входа для...

Как написать библиотеку для работы с сокетами?
Всем привет. Я написал программу клиент-сервер,передающую некий буфер серверу. Теперь хочу сделать это все в виде DLL библиотеки,однако...

58
COM‐пропагандист
 Аватар для Замабувараев
936 / 785 / 149
Регистрация: 18.12.2014
Сообщений: 2,256
Записей в блоге: 4
23.12.2024, 13:45
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от testuser2 Посмотреть сообщение
класс basic_string и класс variant
Которые всего лишь скрывают под собой вызовы функций из библиотеки автоматизации.
В обычном случае этими расширениями можно пренебречь и вызывать функции из oleaut32.dll напрямую.
0
1412 / 878 / 93
Регистрация: 08.02.2017
Сообщений: 3,753
Записей в блоге: 2
23.12.2024, 14:04
Цитата Сообщение от Замабувараев Посмотреть сообщение
Которые всего лишь скрывают под собой вызовы функций из библиотеки автоматизации.
Но в какой-то степени это ведь можно назвать классом. Есть объект и есть какие-то невидимые функции его обслуживающие. Причем неплохо если бы это выглядело как класс, допутим вызов каких-то методов через точку (str1.Len) как это реализовано во многих современных языках. Во всех языках есть представление строки как массива, в VB нет, черт возьми опять же.
0
COM‐пропагандист
 Аватар для Замабувараев
936 / 785 / 149
Регистрация: 18.12.2014
Сообщений: 2,256
Записей в блоге: 4
23.12.2024, 15:08
Цитата Сообщение от testuser2 Посмотреть сообщение
Но в какой-то степени это ведь можно назвать классом
Микрософтовская причуда, которая поставляется с комплекте Visual Studio.
Берём какой‐нибудь другой компилятор, например, GCC. И там уже не будет этих basic_string и variant. Есть только стандартные структуры типа BSTR и VARIANT. Корпорация выпускающая компилятор GCC вправе создать свои классы, которые будут инкапсулировать BSTR и VARIANT и назвать их например b_str и Variant, и наделать к ним других методов, например, GetLength, а не len.
Поэтому basic_string и variant — это никакой не межъязыковой стандарт.
Межъязыковой стандарт — это BSTR и VARIANT, на них и надо опираться.
1
 Аватар для Argus19
1732 / 476 / 78
Регистрация: 24.09.2017
Сообщений: 2,573
Записей в блоге: 27
23.12.2024, 21:01  [ТС]
Коллеги, я всей душой приветствую обмен информацией. Всегда появляется важная информация. Но хотелось бы примеров.
0
1412 / 878 / 93
Регистрация: 08.02.2017
Сообщений: 3,753
Записей в блоге: 2
24.12.2024, 02:24
Argus19, при работе с внешними библиотеками важно понимать несколько вещей
1) VB6/VBA стандартно поддерживает только тип вызова stdcall, поэтому в c++ библиотеке надо делать stdcall-экспорт функций. Если поставить дополнение CDeclFix The trick-а, то можно будет работать и с cdecl - стандартным типом вызова для C/C++.
2)Большие типы, такие как массивы, строки, структуры, Variant из VB во внешние вункции передаются всегда по указателю (ByRef). Строку можно передать ByVal, но при этом все равно будет передаваться указатель на буфер строки (если ByRef, то указатель на переменную строки). Variant можно передатm ByVal, но обычно так не делается, а передается он ByRef. Структуры передаются только ByRef поэтому в С++ надо аргумент определять как указатель на структуру
3)аналогию типов VB-C++ можно брать в таблице стандартных типов Windows, там тупо надо смотреть по размерам. Int = Long, char = Byte и т.д. В VB не поддерживаются беззнаковые целые, знакове char наверное это тоже надо учитывать.
4)Понимание структуры стандартных типов. Строковая переменная в VB это то же самое что переменная типа Long в которую записан указатель на буфер строки, только она обрабатывается как строка. Переменная массива это то же самое, тольк записан указатель на структуру safearray, в переменной объекта указатель на структуру объекта.
Со стороны С++ думаю объяснять не нужно там все должно быт просто )
1
Модератор
10069 / 3914 / 886
Регистрация: 22.02.2013
Сообщений: 5,863
Записей в блоге: 79
24.12.2024, 06:29
http://bbs.vbstreets.ru/viewto... &p=6618721
1
 Аватар для Argus19
1732 / 476 / 78
Регистрация: 24.09.2017
Сообщений: 2,573
Записей в блоге: 27
24.12.2024, 20:46  [ТС]
Цитата Сообщение от testuser2 Посмотреть сообщение
при работе с внешними библиотеками важно понимать несколько вещей
Гран мерси. Я же писал, что сделал набросок, чтобы самому не забыть.
Я всё понимаю, понимаю, что мои знания поверхностны и обывочны. Допишите статью с примерами и укажите ваше авторство. Нет проблем.
Я работаю в фармацевтической кампании, кругом одни дебилы с искренними глазами. Учиться никто не хочет. Мне пока 64 года и я ничего не могу изменить. Сейчас основная задача: научиться вытаскивать прошивки из контроллеров SIEMENS, сохранить их на серваке и при необходимости залить обратно. Если напишете пошаговую инструкцию, буду весьма признателен. И, даже, если я научусь это делать, передать знания, мне некому. Всем на всё насрать. Все искренне хотят сделать "как лучше". Горит всё. И завод налетает на кучу бабок.
0
Вернулся
 Аватар для HackerVlad
1782 / 677 / 46
Регистрация: 10.09.2021
Сообщений: 2,840
24.12.2024, 21:19
У нас же импортозамещение на первом месте. Газовые турбины SIEMENS например поменяют на новые российского производства. Надеюсь уже произвели, чтобы не зависеть от немцев.

Добавлено через 55 секунд
Хотя при чём тут программирование... Там явно не на VB6 всё это ПО...
0
 Аватар для Argus19
1732 / 476 / 78
Регистрация: 24.09.2017
Сообщений: 2,573
Записей в блоге: 27
24.12.2024, 23:42  [ТС]
Цитата Сообщение от HackerVlad Посмотреть сообщение
У нас же импортозамещение на первом месте. Газовые турбины SIEMENS например поменяют на новые российского производства. Надеюсь уже произвели, чтобы не зависеть от немцев.
Вы уверены, что у вас нет нездорового оптимизма? Вы, вообще в курсе, что именно преподают в сегодняшних универах?
Препод даже не знает о современных твердотелках с двумя входами: Вход "Вкл" и переход через ноль. Т.к. IGBT транзисторы это сложно. он будет нам втирать, как отключать тиристоры RC-цепочкой. которые надо будет считать. Высший пилотаж? Я таких инженеров скоро убивать буду. Достали отстоем из прошлого века.
Цитата Сообщение от HackerVlad Посмотреть сообщение
Хотя при чём тут программирование... Там явно не на VB6 всё это ПО...
Ясен пень, гостированы языки LD, FBD, и какая-то паскалеподбная хрень, но нам упорно читают С++, На самом деле С. Это годится только для Arduino. Главное, диплом будет.
И пусть ракеты падают.
0
1412 / 878 / 93
Регистрация: 08.02.2017
Сообщений: 3,753
Записей в блоге: 2
05.10.2025, 11:15
При содействии deepserk сделал простую библиотеку с одной функцией, перемножающей два числа типа double на Visual Studio.
Делал так: при создании проекта выбрал "Библиотека динамической компоновки с экспортом", название проекта "Dll1".
При создании проекта автоматически создаются файлы Dll1.h, dllmain.cpp, pch.h
В dllmain.cpp почти ни чего менять не нужно, только добавить сверху #include "pch.h"
dllmain.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "pch.h" // Используйте "stdafx.h", если проект использует предкомпилированные заголовки
 
BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

Создаем Dll1.cpp и добавляем в него код
Dll1.cpp
C++
1
2
3
4
5
6
7
8
9
#include <Windows.h> 
#include "pch.h"
//#include "framework.h"
#include "Dll1.h"
 
// Экспортируемая функция умножения
double __stdcall Multiply(double a, double b) {
    return a * b;
}

Dll1.h
C++
1
2
3
4
5
6
7
8
#pragma once
#ifdef DLL1_EXPORTS
#define DLL1_API __declspec(dllexport)
#else
#define DLL1_API __declspec(dllimport)
#endif
 
extern "C" DLL1_API double __stdcall Multiply(double a, double b);

"Проект" -> "Добавить новый элемент" -> "Код" -> "Файл определения модуля (.def)"
Dll1.def
C++
1
2
3
LIBRARY Dll1
EXPORTS
    Multiply @1

в pch.h ни чего неменяем
Далее нужно перевести проект из режима "Debug" в "Release", "Сборка" - > "Собрать решение"
Тест в vba
Visual Basic
1
2
3
4
5
6
Public Declare PtrSafe Function Multiply Lib "C:\Users\User\source\repos\Dll1\Release\DLL1.dll" _
     (ByVal a As Double, ByVal b As Double) As Double
 
Sub safdsf()
    debug.print Multiply(4#, 5#)
End Sub
Добавлено через 16 минут
Следующей задачей хотелось бы сделать com-библиотеку, подключаемую в референсах в которой должна быть встроена tlb, а в ней задекларирована функция также, как в vbe7.dll
Так определены функции в vbe7.dll
Кликните здесь для просмотра всего текста
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[
      dllname("VBE7.DLL"),
      uuid(35BFBDA0-2BCC-1069-82D5-00DD010EDFAA),
      helpcontext(0x000f6ec4)
    ]
    module Strings {
        [entry(516), helpcontext(0x000f665f)]
        short _stdcall Asc([in] BSTR String);
        [entry(537), helpcontext(0x000f6e9f)]
        BSTR _stdcall _B_str_Chr([in] long CharCode);
        [entry(608), helpcontext(0x000f64e2)]
        VARIANT _stdcall _B_var_Chr([in] long CharCode);
        [entry(517), helpcontext(0x000f6ea0)]
        BSTR _stdcall _B_str_LCase([in] BSTR String);
        [entry(518), helpcontext(0x000f653d)]
        VARIANT _stdcall _B_var_LCase([in] VARIANT* String);
        [entry(631), helpcontext(0x000f6e99)]
        BSTR _stdcall _B_str_Mid(
                        [in] BSTR String, 
                        [in] long Start, 
                        [in, optional] VARIANT* Length);
        [entry(632), helpcontext(0x000f6e9a)]

Если сделать такую же библиотеку, то не нужно будет писать определения, Declare, все функции будут доступны, только как это сделать, наверное сложно..
2
Модератор
Эксперт Java
 Аватар для alecss131
2903 / 1408 / 413
Регистрация: 11.08.2017
Сообщений: 4,517
Записей в блоге: 2
05.10.2025, 11:34
Цитата Сообщение от testuser2 Посмотреть сообщение
#include "pch.h" // Используйте "stdafx.h"
По сути что тот заголовок, что другой это предкомпилированные заголовки, в студии использовалось и то и другое название, первое вроде еще и в других компиляторах будет работать. Не знаю как в VB, но в с/с++ вполне себе можно прожить без них (особенно когда проект мелкий) и если они где-то используются, то должны использоваться везде (включая либы).
Цитата Сообщение от testuser2 Посмотреть сообщение
BOOL APIENTRY DllMain
Если там нету специфичного кода инициализации библиотеки, то смысла писать это нету, все будет работать и так.
Как пишется на сайте мелкомягких, можно обойтись без def файла добавив предложение alias в оператор Declare
Да и если код чисто Сишный, то есть без классов и всего плюсового, то имхо лучше писать код в .c файлах, а не .cpp и тогда можно обойтись без extern "C"
1
1412 / 878 / 93
Регистрация: 08.02.2017
Сообщений: 3,753
Записей в блоге: 2
05.10.2025, 14:34
Цитата Сообщение от alecss131 Посмотреть сообщение
то имхо лучше писать код в .c файлах, а не .cpp и тогда можно обойтись без extern "C"
Интересно, можно писать на чистом си

Добавлено через 1 час 28 минут
Собрал com-библиотеку с одной функцией (Multiply), библиотека подключается в референсах, функция видна в обозревателе обхектов. Но при попытке использовать функцию возникает ошибка File not found: SimpleMathCOM.dll с чем это может быть связано обхясните пожалуйста Господа The trick, alecss131

Добавлено через 1 минуту
Думал скину проектик, а он там на 200+ мегов.. пустой-то

Добавлено через 4 минуты
SimpleMathCOM.cpp
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
// SimpleMathCOM.cpp: реализация экспортов DLL.
 
 
#include <Windows.h> 
#include "pch.h"
#include "framework.h"
#include "resource.h"
#include "SimpleMathCOM_i.h"
#include "dllmain.h"
#include "xdlldata.h"
 
 
using namespace ATL;
 
// Используется, чтобы определить, можно ли выгрузить DLL средствами OLE.
_Use_decl_annotations_
STDAPI DllCanUnloadNow(void)
{
#ifdef _MERGE_PROXYSTUB
    HRESULT hr = PrxDllCanUnloadNow();
    if (hr != S_OK)
        return hr;
#endif
    return _AtlModule.DllCanUnloadNow();
}
 
// Возвращает фабрику класса для создания объекта требуемого типа.
_Use_decl_annotations_
STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID* ppv)
{
#ifdef _MERGE_PROXYSTUB
    HRESULT hr = PrxDllGetClassObject(rclsid, riid, ppv);
    if (hr != CLASS_E_CLASSNOTAVAILABLE)
        return hr;
#endif
    return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
}
 
// DllRegisterServer - добавляет записи в системный реестр.
_Use_decl_annotations_
STDAPI DllRegisterServer(void)
{
    // регистрирует объект, библиотеку типов и все интерфейсы в библиотеке типов
    HRESULT hr = _AtlModule.DllRegisterServer();
#ifdef _MERGE_PROXYSTUB
    if (FAILED(hr))
        return hr;
    hr = PrxDllRegisterServer();
#endif
    return hr;
}
 
// DllUnregisterServer - удаляет записи из системного реестра.
_Use_decl_annotations_
STDAPI DllUnregisterServer(void)
{
    HRESULT hr = _AtlModule.DllUnregisterServer();
#ifdef _MERGE_PROXYSTUB
    if (FAILED(hr))
        return hr;
    hr = PrxDllRegisterServer();
    if (FAILED(hr))
        return hr;
    hr = PrxDllUnregisterServer();
#endif
    return hr;
}
 
// DllInstall - добавляет и удаляет записи системного реестра для конкретного пользователя и компьютера.
STDAPI DllInstall(BOOL bInstall, _In_opt_  LPCWSTR pszCmdLine)
{
    HRESULT hr = E_FAIL;
    static const wchar_t szUserSwitch[] = L"user";
 
    if (pszCmdLine != nullptr)
    {
        if (_wcsnicmp(pszCmdLine, szUserSwitch, _countof(szUserSwitch)) == 0)
        {
            ATL::AtlSetPerUserRegistration(true);
        }
    }
 
    if (bInstall)
    {
        hr = DllRegisterServer();
        if (FAILED(hr))
        {
            DllUnregisterServer();
        }
    }
    else
    {
        hr = DllUnregisterServer();
    }
 
    return hr;
}
 
// Экспортируемая функция
extern "C" double __stdcall Multiply(double a, double b)
{
    return a * b;
}

SimpleMathCOM.def
C++
1
2
3
4
5
6
7
8
9
10
11
; SimpleMathCOM.def: объявляет параметры модуля.
 
LIBRARY SimpleMathCOM
 
EXPORTS
    DllCanUnloadNow     PRIVATE
    DllGetClassObject   PRIVATE
    DllRegisterServer   PRIVATE
    DllUnregisterServer PRIVATE
    DllInstall          PRIVATE
    Multiply @1

SimpleMathCOM.idl
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
// SimpleMathCOM.idl: источник языка IDL для SimpleMathCOM
//
 
// Этот файл будет обработан средством MIDL для
// создание библиотеки типов ($handlersafeidlname$.tlb) и кода маршалирования.
 
import "oaidl.idl";
import "ocidl.idl";
 
[
    uuid(8ccd6502-788a-41e1-8886-d80a370ca5be),
    version(1.0),
    helpstring("Simple Math COM Library")
]
library SimpleMathCOMLib
{
    importlib("stdole2.tlb");
    
    [
        uuid(d61a41aa-07eb-4d91-ba9f-4deb7137f80a),
        dllname("SimpleMathCOM.dll"),
        helpstring("Math functions module")
    ]
    module MathFunctions{
        [entry("Multiply")]
        double __stdcall Multiply(
            [in] double a,
            [in] double b);
    };
};


Добавлено через 4 минуты
Вот сам проект

Добавлено через 1 час 6 минут
Цитата Сообщение от testuser2 Посмотреть сообщение
возникает ошибка File not found: SimpleMathCOM.dll
Все работает на самом деле, просто нужно, чтобы библиотека лежала в системной папке или одной папке с vba-проектом. Причем вызов функции работает через declare и также при подключении библиотеки в референсах, так что этот проект можно брать за образец, там коенчо может быть много лишнего, но, сама dll-ка получается всего 34+ кб. Можно смело пилить свой сишный фреймворк под VBxx
1
1412 / 878 / 93
Регистрация: 08.02.2017
Сообщений: 3,753
Записей в блоге: 2
07.10.2025, 01:58
Цитата Сообщение от testuser2 Посмотреть сообщение
обхясните
опечатка, частенько мажу мимо "ъ".
0
 Аватар для Argus19
1732 / 476 / 78
Регистрация: 24.09.2017
Сообщений: 2,573
Записей в блоге: 27
07.10.2025, 08:56  [ТС]
Цитата Сообщение от testuser2 Посмотреть сообщение
uuid(8ccd6502-788a-41e1-8886-d80a370ca5be)
Как вы определяете uuid? Как я понимаю, он должен быть уникальным?
0
1412 / 878 / 93
Регистрация: 08.02.2017
Сообщений: 3,753
Записей в блоге: 2
07.10.2025, 12:31
Argus19, я их сгенерил на первом попавшемся онлайн-генераторе, забыл об этом упомянуть, еще о том, что лучше компилировать с повышенными правами, чтобы библиотека автоматически зарегилась.

Добавлено через 18 минут
Как я еще понял, [entry("Multiply")] можно было опустить, или указать ординал [entry(1)]. В vbe7.dll везде используются ординалы.

Добавлено через 1 минуту
А прописываются ординалы (номера функций), наверное в файле .def
0
1412 / 878 / 93
Регистрация: 08.02.2017
Сообщений: 3,753
Записей в блоге: 2
27.10.2025, 12:48
Цитата Сообщение от testuser2 Посмотреть сообщение
сделал простую библиотеку
Еще одна версия гайда по написанию Dll, с учетом некоторых замечаний и попытками разобраться в некоторых интерфесных моментов и пр. В данном случае будет библиотека с 2мя функциями (Multiply, Divide) одна из которых реализована на С++, другая на чистом C. Также особенностью данного примера является то, что у меня получилось убрать очень много "лишнего" из кода, не теряя при работоспособности.
Далее по пунктам:
* Cоздаем проект библиотеки (Dll4).
* Заходим в настройки проекта >> C/C++ >> Соглашеие о вызовах выбираем __stdcall (/Gz). После этого все создаваемые функции в проекте по умолчанию будут __stdcall и не нужно будет это специально прописывать. Такую настройку можно конечно делать, не обязательно для всего проекта, а можно только для отдельных модулей (файлов)
* Добавляем файл .def. Он автоматически прописывается в свойствах проекта (Компоновщик >> Ввод). Однако если мы удалим/исключим его из проекта (его также надо будет удалить из свойств проекта), или надо будет изменить его название, то в дальнейшем надо его будет прописывать в свойствах руками.
Dll4.def
Code
1
2
3
4
LIBRARY Dll4
EXPORTS
    Multiply @1
    Divide @2

* Добавляем файлы MulFunc.cpp и DivFunc.c
MulFunc.cpp
C++
1
2
3
4
5
6
#include "pch.h"
//#include "Dll4.h"
 
double Multiply(double a, double b){
    return a * b;
}

DivFunc.c
C
1
2
3
4
5
6
#include "pch.h"
//#include "Dll4.h"
 
double Divide(double a, double b){
    return (b != 0.0) ? a / b : 0.0;
}

* Dll4.h добавляется автоматически. В нем я оставил стандартные штуки, но оставил незакомментированными только экспорты.
Dll4.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
// Приведенный ниже блок ifdef — это стандартный метод создания макросов, упрощающий процедуру
// экспорта из библиотек DLL. Все файлы данной DLL скомпилированы с использованием символа DLL4_EXPORTS
// Символ, определенный в командной строке. Этот символ не должен быть определен в каком-либо проекте,
// использующем данную DLL. Благодаря этому любой другой проект, исходные файлы которого включают данный файл, видит
// функции DLL4_API как импортированные из DLL, тогда как данная DLL видит символы,
// определяемые данным макросом, как экспортированные.
//#ifdef DLL4_EXPORTS
//  #define DLL4_API __declspec(dllexport)
//#else
//  #define DLL4_API __declspec(dllimport)
//#endif
 
// Этот класс экспортирован из библиотеки DLL
//class DLL4_API CDll4 {
//public:
//  CDll4(void);
//  // TODO: добавьте сюда свои методы.
//};
 
//extern DLL4_API int nDll4;
 
//DLL4_API int fnDll4(void);
 
//#ifdef __cplusplus
//extern "C" {
//#endif
    double Multiply(double a, double b);
    double Divide(double a, double b);
//#ifdef __cplusplus
//}
//#endif

* В свойствах DivFunc.c (С/C++ >> Предварительно откомпилированные заголоки) нужно выбрать "Не использовать предварительно сокмпилированные заголовки". Без этого у меня библиотека не компилировалась, наверное потому, что C не поддерживате эти самые..
Вроде бы все, надеюсь ни чего не забыл. Что не получилось у меня, это избавиться от #include "pch.h" в каждом модуле кода. От самого pch.h, то беж от предкомпилированных заголовков я отказываться не хотел, поскольку вещь априоре должна быть нужная, наверняка это важно при компиляции под разную битность.

Добавлено через 7 минут
Тест в VB/VBA
Visual Basic
1
2
3
4
5
6
7
8
9
Option Explicit
 
Declare PtrSafe Function Multiply Lib "C:\Users\User\source\repos\Dll4\Release\DLL4.dll" Alias "#1" (ByVal a As Double, ByVal b As Double) As Double
Declare PtrSafe Function Divide Lib "DLL4.dll" Alias "#2" (ByVal a As Double, ByVal b As Double) As Double
 
Sub TestDll()
    MsgBox Multiply(6, 7)
    MsgBox Divide(42, 7)
End Sub
0
Модератор
Эксперт Java
 Аватар для alecss131
2903 / 1408 / 413
Регистрация: 11.08.2017
Сообщений: 4,517
Записей в блоге: 2
27.10.2025, 16:37
Цитата Сообщение от testuser2 Посмотреть сообщение
от предкомпилированных заголовков я отказываться не хотел, поскольку вещь априоре должна быть нужная, наверняка это важно при компиляции под разную битность
Это имеет смысл и важно только если крупный проект и надо ускорить сборку. А так кроме ускорения сборки, а точнее пересборки, толку от этих заголовков нету. Их наличие будет заметно только на очень уж крупных проектах.
В студийном компиляторе от подобных вещей __declspec(dllexport) отказываться не стоит, иначе не будет видно функции, а при отказе от extern "C" плюсовые функции будут менять имена, хотя при наличии def файла это не так важно, так как используются номера а не имена.
Для 64 бит различия между stdcall, cdecl и fastcall будет только в том кто чистит стэк. Получается что в cdecl стэк чистит вызывающая функция, а в двух других вызываемая. Есть еще thiscall, но он чисто плюсовый, в регистре ecx указатель this, стэк чистит вызываемая функция.
1
1412 / 878 / 93
Регистрация: 08.02.2017
Сообщений: 3,753
Записей в блоге: 2
27.10.2025, 16:51
Цитата Сообщение от alecss131 Посмотреть сообщение
от подобных вещей __declspec(dllexport) отказываться не стоит, иначе не будет видно функции, а при отказе от extern "C"
Эти штуки, они просто какие-то гнустые по одному своему виду и выглядят не понятно, просто сбивают с толку, когда их убираешь - просто вау! все как-будто становится нормальней. Вы не могли бы уточнить, что значит "не будет видно функции".
0
Модератор
Эксперт Java
 Аватар для alecss131
2903 / 1408 / 413
Регистрация: 11.08.2017
Сообщений: 4,517
Записей в блоге: 2
27.10.2025, 21:55
Цитата Сообщение от testuser2 Посмотреть сообщение
"не будет видно функции".
Студийный компилятор таким образом экспортирует функции в dll, без них в списке экспорта dll файла функции просто не будет. Иначе говоря без этого вызов функции из dll не будет производиться.

Это вот эта штука __declspec(dllimport) является не обязательной, работает без нее, но она сэкономит пару ассемблерных инструкций разве что.

Советую поиграться с утилитой dumpbin из студии, например так dumpbin /exports name.dll на выходе покажется все то что можно вызывать из dll, там как раз будут все те функции которые помечены __declspec(dllexport)
Это в гнутом компиляторе (mingw/gcc) такое не нужно, там все функции экспортируются.

Добавлено через 4 часа 55 минут
testuser2, Вот пример, нету Вашего языка, попробуйте.
Все выполнять в x64 Native Tools Command Prompt for VS 2022
вот файл test.cpp, демонстрирующий разные результаты
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
extern "C" __declspec(dllexport) int __stdcall add(int a, int b);
extern "C" int __stdcall fun(int a, int b);
__declspec(dllexport) int __stdcall mul(int a, int b);
extern "C" __declspec(dllexport) int __stdcall sub(int a, int b);
 
int add(int a, int b){
    return a + b;
}
 
int fun(int a, int b){
    return a;
}
 
int mul(int a, int b){
    return a * b;
}
 
int sub(int a, int b){
    return a - b;
}
Здесь нету точки входа, нету предкомпилированных заголовков, у одной функции нету extern "C", а у одной нету __declspec(dllexport)
соберем ее, первая команда компиляция, вторая линковка в dll
Windows Batch file
1
2
cl /c /MD /O2 /std:c++17 test.cpp
link /DLL /NODEFAULTLIB /NOENTRY test.obj
и выполним
Windows Batch file
1
dumpbin /EXPORTS test.dll
на выходе интересующий нас результат
Windows Batch file
1
2
3
4
5
    ordinal hint RVA      name
 
          1    0 00001000 ?mul@@YAHHH@Z
          2    1 00001010 add
          3    2 00001020 sub
Где видно что в экспорте нету функции fun у которой как раз не было __declspec(dllexport), что значит что вызвать ее из этой dll не выйдет. У функции mul имя поменялось на ?mul@@YAHHH@Z так как у нее не было extern "C", этот процесс строго определенный и известный (Name mangling)
И небольшой тестовый код main.c
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
#include <stdio.h>
#include <Windows.h>
 
typedef int(__stdcall *fun)(int, int);
 
int main(){
    HMODULE dll = LoadLibraryExA("test.dll", NULL, 0);
    if (!dll) {
        printf("cant load library\n");
        return 1;
    }
    int a = 2;
    int b = 3;
    fun mul1 = (fun)GetProcAddress(dll, MAKEINTRESOURCE(1));
    if (mul1){
        printf("mul1(%d, %d) = %d\n", a, b, mul1(a, b));
    }
    fun add2 = (fun)GetProcAddress(dll, MAKEINTRESOURCE(2));
    if (add2){
        printf("add2(%d, %d) = %d\n", a, b, add2(a, b));
    }
    fun mul = (fun)GetProcAddress(dll, "?mul@@YAHHH@Z");
    if (mul){
        printf("mul+(%d, %d) = %d\n", a, b, mul(a, b));
    }
    fun sub = (fun)GetProcAddress(dll, "sub");
    if (sub){
        printf("sub(%d, %d) = %d\n", a, b, sub(a, b));
    }
    FreeLibrary(dll);
    return 0;
}
вывод будет
Windows Batch file
1
2
3
4
mul1(2, 3) = 6
add2(2, 3) = 5
mul+(2, 3) = 6
sub(2, 3) = -1
В первом случае я вызываю mul по номеру ordinal из dumpbin, во втором add так же по номеру, в третьем функцию mul по имени (надо использовать все длинное), а в четвертом sub по короткому имени
Попробуйте вызвать собранную dll из этого поста из своего языка. По сути это минимальный пример dll.
1
1412 / 878 / 93
Регистрация: 08.02.2017
Сообщений: 3,753
Записей в блоге: 2
28.10.2025, 01:47
Цитата Сообщение от alecss131 Посмотреть сообщение
Студийный компилятор таким образом экспортирует функции в dll, без них в списке экспорта dll файла функции просто не будет. Иначе говоря без этого вызов функции из dll не будет производиться.
Тот код, который я выкладывал (+ описаные настройки проекта и модулей), компилится в рабочую библиотеку с нормальными экспортными именами, я их смотрю в проге Dll Export Viewer от Nirsoft. В VBA можно объявить функцию по имени (не по ординалу) и все работает.

Добавлено через 8 минут
Цитата Сообщение от alecss131 Посмотреть сообщение
Это имеет смысл и важно только если крупный проект и надо ускорить сборку. А так кроме ускорения сборки, а точнее пересборки, толку от этих заголовков нету. Их наличие будет заметно только на очень уж крупных проектах.
Я пробовал исключить из проекта "pch.h" и закомментировать #include "pch.h", в итоге библиотека не компилится. Потом пробовал вернуть обратно и восстановить компиляцию все-равно не получилось. В итоге я смекнул, что "pch.h" это какой-то неубираемый костыль, который лучше не трогать.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
28.10.2025, 01:47

Составить библиотеку программ для решения матричных уравнений
Помогите пожалуйста, очень срочно! написать программу в турбо паскале!зарание спасибо! и желательно с блок схемой Составить...

Copy Hook. Или как написать библиотеку для перехвата копирования
Возник такой интересный вопрос. Я пользуюсь программой SuperCopier2. Эта программа заменяет стандартный диалог копирования\перемещения, но...

Как написать тест программ для след класса
Задача написать тест программу кот выполняет проверку Student class: The three-argument Student class constructor The enroll member...

Как используя библиотеку fsream записать в одну строку результаты из двух программ?
У меня есть имеется 2 программы, которые записывают результат в csv файл. Из первой программы записывается значение Opt из второй все...

Ищу библиотеку для создания программ обмена между ПЛК и ПК через программатор AMSAMOTION (USB - MPI адаптер)
И второй вопрос - имеется программатор AMSAMOTION (USB - MPI адаптер). Где можно скачать библиотеку и документацию к драйверу для данного...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Часы с термометром и праздничным календарем
yariko 12.11.2026
Сегодня мы рассмотрим как можно сделать отличные многофункциональные часы. Итак, поставим конкретную задачу: разработать часы с календарем, двумя термодатчиками, выводом поздравительных сообщений. . .
Транслитерация текста с кириллицы на латиницу (вариант №1)
Maks 11.11.2026
Решил облегчить жизнь себе и коллегам админам при создании электронных почтовых ящиков для пользователей, в результате написал обработку "Транслитерация текста" с кириллицы на латиницу, а в ней. . .
Книги по геймдизайну, левел-дизайну, игровым механикам и проектированию игрового опыта
8Observer8 08.11.2026
Содержание блога | English Version 1. 2003 - 06 - Designing Virtual Worlds (1st Edition) Автор: Richard A. Bartle | Объем: 768 стр. Ссылки: Amazon . . .
Родители токсичные абьюзеры по отношению к своим детям ругают их оскорбляют не любят
zorxor 08.11.2026
Жить в атмосфере постоянных оскорблений, критики и холодности со стороны родителей — это тяжелое и болезненное испытание, которое оставляет глубокие эмоциональные раны. Токсичное и абьюзивное. . .
Как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Ответ от Джемени ИИ.
zorxor 08.11.2026
Джемени, как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Многие люди, возвращаясь домой, сразу переодеваются в максимально свободную одежду или вовсе предпочитают. . .
Паттерн очереди действий/команд (Action / Command Queue). Система очереди действий и кат-сцен с SDL3 Callbacks, cglm и OpenGL
8Observer8 07.11.2026
Содержание блога | English Version Руководство для начинающих по реализации паттерна очереди действий/ команд (Action / Command Queue) на C++ (C++20) с использованием официального SDL3 Callbacks. . .
Проверка полного ФИО в типовом справочнике
Maks 07.11.2026
Решение реализовано в конфигурации КА2, на примере справочника "КонтактныеЛицаПартнеров". Задача: Запрет инициалов. Не допускаеть использование сокращений вида "И. И. ", "И. И. ", "И И" и. . .
Про "Windows must die!"
kumehtar 04.11.2026
Знаете, чет накатило. . . . Когда-то это было почти боевым кличем: мол, нормальный человек сидит на DOS, OS/ 2 или Linux, а вот это вот - Must Die. А теперь человек произносит «мастдай» с усмешкой - и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru