Форум программистов, компьютерный форум, киберфорум
QBasic
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.91/32: Рейтинг темы: голосов - 32, средняя оценка - 4.91
991 / 217 / 21
Регистрация: 20.05.2016
Сообщений: 945
Записей в блоге: 17
1

Подключить библиотеку dll

01.03.2017, 09:35. Показов 6356. Ответов 166
Метки нет (Все метки)

Данным диалектом Бейсика не пользуясь, но иногда здесь бываю. Решил немного поучаствовать. Собственно вопрос в следующем: можно ли пользоватся сторонними библиотеками в этом диалекте, насколько сложен процесс использования? Цель - есть своя xll для VBA, можно убрать обертку будет dll, выложу здесь для тех кто много считает, большими числами) (Гугл не спрашивал ибо важно понять, есть целесообразность в данном продукте?)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.03.2017, 09:35
Ответы с готовыми решениями:

Не получается подключить библиотеку Unmanaged.dll (Firefox nss3.dll)
Здравствуйте, начал изучать c#, очень понравилась тема декриптования, для начала решил из...

Подключить библиотеку dll
Имеется программа nircmd.exe, которая с помощью батника позволяет выполнять различные комманды К...

Как подключить dll библиотеку?
Здраствуйте, есть такой вопрос, как можно подключить *.dll библиотеку к код блокс или к ...

Как подключить .dll библиотеку?
Есть готовый код на С++...

166
Модератор
8671 / 3208 / 838
Регистрация: 22.02.2013
Сообщений: 4,793
Записей в блоге: 78
05.04.2018, 11:29 101
Цитата Сообщение от locm Посмотреть сообщение
Он и передается.
Нет. BSTR - это указатель на строку с префиксом. Указатель на BSTR это указатель на указатель на строку с префиксом. Ты передаешь указатель на строку с префиксом.

Цитата Сообщение от Pro_grammer Посмотреть сообщение
И GUIDs не совпадает у меня, вернее один совпадает.
Цитата Сообщение от locm Посмотреть сообщение
Тоже самое. Но с такими ID не работает.
С чем? В коде locm'а:
CLSID - {322E4E2F-E105-4BB0-9B21-4C2A6AF6DE2D}
IID - {D83F0A2C-3940-4237-B88E-7097479D01C6}

Мои:
CLSID - {322E4E2F-E105-4BB0-9B21-4C2A6AF6DE2D}
IID - {D83F0A2C-3940-4237-B88E-7097479D01C6}

Что не совпадает?

Я понял что не совпадает. Это TLBID а не CLSID. Это идентификатор библиотеки типов, а не идентификатор класса. В данном случае он не нужен.

Добавлено через 13 минут
Цитата Сообщение от locm Посмотреть сообщение
Просто часть методов наследуется от IUnknown.
Или от IDispatch тогда только один метод ShowMsgBox будет (dual интерфейс).
0
2783 / 1294 / 167
Регистрация: 28.10.2011
Сообщений: 4,790
Записей в блоге: 6
05.04.2018, 11:40 102
Цитата Сообщение от The trick Посмотреть сообщение
Нет. BSTR - это указатель на строку с префиксом.
В описании типа переменной метода ShowMsgBox применен псевдотип p-bstr предназначенный для передачи BSTR строк в COM методы.
0
Модератор
8671 / 3208 / 838
Регистрация: 22.02.2013
Сообщений: 4,793
Записей в блоге: 78
05.04.2018, 11:44 103
locm, в методе используется тип BSTR*:
Подключить библиотеку dll
0
2783 / 1294 / 167
Регистрация: 28.10.2011
Сообщений: 4,790
Записей в блоге: 6
05.04.2018, 12:25 104
Зачем передавать указатель на указатель?

Решил исправить это
Visual Basic
1
2
3
4
Public Sub ShowMsgBox( _
           ByVal sText As String)
    MsgBox sText
End Sub
Скомпилировал, но теперь DLL опять не загружается. CoCreateInstance возвращает 80040111.

С обычными DLL все намного проще.
0
Модератор
8671 / 3208 / 838
Регистрация: 22.02.2013
Сообщений: 4,793
Записей в блоге: 78
05.04.2018, 12:42 105
Цитата Сообщение от locm Посмотреть сообщение
Для чего было передавать указатель на указатель?
Для того чтобы передать параметр по ссылке и не делать внутреннюю копию BSTR строки, т.к. при передаче параметра по значению его модификация не должна сказываться на переданный параметр. Это элементарно, тоже самое что вместо передачи копии структуры передавать указатель на структуру. В функции он не изменяется поэтому передача по ссылке намного производительней.

Цитата Сообщение от locm Посмотреть сообщение
Решил исправить это
Для чего? В чем сложность передать указатель? И все сразу заработает. Это не проблема технологии или класса, а неправильное использование.

Цитата Сообщение от locm Посмотреть сообщение
Скомпилировал, но теперь DLL опять не загружается. CoCreateInstance возвращает 80040111.
Потому что идентификаторы изменились, т.к. во-первых не была выставлена в проекте бинарная совместимость, во-вторых изменилось определение интерфейса. Соответственно IID поменялся, следует либо выбирать бинарную совместимость проекта с предыдущей версией DLL и принудительно оставлять прежний IID, либо менять IID в соответствии с новым интерфейсом. Также следует проверить (если не выставлена бинарная совместимость) CLSID.

Цитата Сообщение от locm Посмотреть сообщение
С обычными DLL все намного проще.
Так это и есть обычная DLL, если ей неправильно пользоваться то кто в этом виноват кроме программиста?
0
2783 / 1294 / 167
Регистрация: 28.10.2011
Сообщений: 4,790
Записей в блоге: 6
05.04.2018, 12:57 106
Цитата Сообщение от The trick Посмотреть сообщение
Это элементарно, тоже самое что вместо передачи копии структуры передавать указатель на структуру.
Правильно, указатель на структуру или строку, а не указатель на указатель. Одного указателя достаточно для передачи по ссылке.

Цитата Сообщение от The trick Посмотреть сообщение
Так это и есть обычная DLL
Я про процедурную DLL, а не ActiveX.
0
Модератор
6761 / 2774 / 525
Регистрация: 24.04.2011
Сообщений: 5,262
Записей в блоге: 10
05.04.2018, 13:10 107
На самом деле код рабочий, хотя и отображается всякая фигня. Работает только в Юникодном режиме
Подключить библиотеку dll


Тогда как на VB6 всё красиво
Подключить библиотеку dll
0
991 / 217 / 21
Регистрация: 20.05.2016
Сообщений: 945
Записей в блоге: 17
05.04.2018, 13:10  [ТС] 108
Собрал dll под разную разрядность:
https://www.cyberforum.ru/blog... g5196.html
0
Модератор
8671 / 3208 / 838
Регистрация: 22.02.2013
Сообщений: 4,793
Записей в блоге: 78
05.04.2018, 13:13 109
Цитата Сообщение от locm Посмотреть сообщение
Правильно, указатель на структуру или строку, а не указатель на указатель. Одного указателя достаточно для передачи по ссылке.
Ты путаешь, BSTR - это ссылочный тип, если будет угодно это структура следующего вида:
Visual Basic
1
2
3
Type BSTR
    pStr As Long
End Type
Чтобы мне передать ее по ссылке мне нужно передать указатель на первый элемент.
Передача по ссылке подразумевает модификацию переданного параметра, если поступать как предлагаешь ты, то такого не получится к примеру:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
Sub Foo()
    Dim l As Long
    
    Bar l
    
    Print l
    
End Sub
 
Sub Bar(ByRef pVal As Long)
    pVal = 1234 ' // Изменяем переменную l
End Sub
А теперь попробуй изменить/возвратить строку BSTR передав ее не по указателю.

Цитата Сообщение от locm Посмотреть сообщение
Я про процедурную DLL, а не ActiveX.
ActiveX - частный случай процедурной.

Добавлено через 2 минуты
Pro_grammer, не знаком с синтаксисом PB, но с большой вероятностью ты делаешь ошибку, @ - насколько я понимаю это получение адреса. ты во-первых передаешь строку без префикса, во-вторых передаешь указатель на строку, а нужно указатель на указатель на строку с префиксом (указатель на BSTR)
0
Модератор
6761 / 2774 / 525
Регистрация: 24.04.2011
Сообщений: 5,262
Записей в блоге: 10
05.04.2018, 13:19 110
Цитата Сообщение от The trick Посмотреть сообщение
о-первых передаешь строку без префикса
Да не влияет, результат всё равно не тот, что хотелось, как на VB6
Подключить библиотеку dll
0
Модератор
6761 / 2774 / 525
Регистрация: 24.04.2011
Сообщений: 5,262
Записей в блоге: 10
05.04.2018, 13:23 111
Вот, нашёл ка сработало!!!!
Указатель на указатель, и всё получилось:
Подключить библиотеку dll

Вот такой изврат
PureBasic
1
2
3
4
5
6
7
...
CoInitialize_(0)
  If CoCreateInstance_(?CLSDID_CTest, 0, 1, ?IID_CTest, @cObject.CTest) = 0
    n=@"Всё получилось!"
   cObject\ShowMsgBox(@n)
   cObject\Release()
 EndIf
0
Модератор
8671 / 3208 / 838
Регистрация: 22.02.2013
Сообщений: 4,793
Записей в блоге: 78
05.04.2018, 13:39 112
Pro_grammer, если передавать неправильные параметры что ты ожидаешь? Может быть если ты сделаешь процедурную DLL на PB и передашь туда неправильные параметры то эта DLL будет работать корректно? Я дал код на ассемблере - это самый напростейший уровень, в котором видно как нужно передавать и что все работает.

Добавлено через 4 минуты
Цитата Сообщение от Pro_grammer Посмотреть сообщение
Вот такой изврат
Указатель на ссылочный тип - изврат? По этой логике указатель на структуру с полями указателями - тоже изврат? А списки - тоже изврат?

Добавлено через 2 минуты
Цитата Сообщение от Pro_grammer Посмотреть сообщение
Тогда как на VB6 всё красиво
Потому что в VB6 строки изначально в BSTR формате, а во-вторых согласно библиотеке типов он корректно определяет передачу по ссылке от передачи по значению, не знаю как в PB.

Добавлено через 7 минут
Цитата Сообщение от Pro_grammer Посмотреть сообщение
PureBasic
1
2
3
4
5
6
7
...
CoInitialize_(0)
* If CoCreateInstance_(?CLSDID_CTest, 0, 1, ?IID_CTest, @cObject.CTest) = 0
* * n=@"Всё получилось!"
* *cObject\ShowMsgBox(@n)
* *cObject\Release()
*|/1/>EndIf
Неверно. Где префикс? Потом начнутся вылеты а виновата скорее всего будет COM технология.
Правильно:
PureBasic
1
2
n = SysAllocString(@"Все получилось!")  ' // n - BSTR строка, аналог на C BSTR n = SysAllocString(...)
cObject\ShowMsgBox(@n)
Ну и где тут извращение?
0
Модератор
6761 / 2774 / 525
Регистрация: 24.04.2011
Сообщений: 5,262
Записей в блоге: 10
05.04.2018, 13:47 113
Цитата Сообщение от The trick Посмотреть сообщение
Правильно:
тогда так:
PureBasic
1
2
3
4
5
6
7
CoInitialize_(0)
  If CoCreateInstance_(?CLSDID_CTest, 0, 1, ?IID_CTest, @cObject.CTest) = 0
    
    n=SysAllocString_(@"Всё получилось!") 
    cObject\ShowMsgBox(@n)
    cObject\Release()
 EndIf
Но разницы я в работе не увидел. Ну если это правильнее, то пусть будет так.
0
Модератор
8671 / 3208 / 838
Регистрация: 22.02.2013
Сообщений: 4,793
Записей в блоге: 78
05.04.2018, 14:00 114
Цитата Сообщение от Pro_grammer Посмотреть сообщение
Ну если это правильнее, то пусть будет так.
Это не правильнее, а правильно. Поскольку первый вариант неправильный и может вызывать сбои.
Кликните здесь для просмотра всего текста
Ну еще строку нужно освобождать SysFreeString

Другой момент в том что меня удивляет почему указатель на указатель - это извращение? Ну вот возьми к примеру функцию GetFullPathName в последнем параметре что передается? И таких функций множество.
Еще один момент связан с BSTR, если не хотите передавать BSTR - пишите библиотеку и передавайте LPSTR, LPWSTR. Это не запрещено в COM. Просто DLL написана на VB6 с его BSTR строками.
0
Модератор
6761 / 2774 / 525
Регистрация: 24.04.2011
Сообщений: 5,262
Записей в блоге: 10
05.04.2018, 14:19 115
Цитата Сообщение от The trick Посмотреть сообщение
почему указатель на указатель - это извращение?
Не бери в голову
Написал исключительно в контексте использования того же самого в VB6, где я просто передал строку, не задумываясь об указателях
Visual Basic
1
2
3
4
Private Sub Form_Load()
Set CTest = CreateObject("TestLib.CTest")
CTest.ShowMsgBox ("AAAAA")
End Sub
А в общем случае ни чего против указателей на указатель не имею, тем более, что это явление не редкое в других ЯП.
0
2783 / 1294 / 167
Регистрация: 28.10.2011
Сообщений: 4,790
Записей в блоге: 6
05.04.2018, 14:31 116
Цитата Сообщение от The trick Посмотреть сообщение
Передача по ссылке подразумевает модификацию переданного параметра
В данном случае (метод ShowMsgBox), строка не модифицируется и логично передавать ее просто по указателю, как WinAPI функции MessageBox.
0
Модератор
8671 / 3208 / 838
Регистрация: 22.02.2013
Сообщений: 4,793
Записей в блоге: 78
05.04.2018, 15:43 117
Цитата Сообщение от locm Посмотреть сообщение
В данном случае (метод ShowMsgBox), строка не модифицируется и логично передавать ее просто по указателю, как WinAPI функции MessageBox.
Я уже написал для чего я так сделал.
0
Модератор
8671 / 3208 / 838
Регистрация: 22.02.2013
Сообщений: 4,793
Записей в блоге: 78
05.04.2018, 19:54 118
В качестве демонстрации платформо-независимости COM, сделал небольшой пример на 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
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
#include <stddef.h>
#include <stdlib.h>
 
typedef struct {
    int     Data1;
    short   Data2;
    short   Data3;
    char    Data4[8];
} GUID;
 
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) const GUID name = {l, w1, w2, {b1, b2, b3, b4, b5, b6, b7, b8}}
 
// {128DAF0F-76DB-4950-9073-088A20F22265} идентификатор интерфейса ISum
DEFINE_GUID(IID_ISum, 
    0x128daf0f, 0x76db, 0x4950, 0x90, 0x73, 0x8, 0x8a, 0x20, 0xf2, 0x22, 0x65);
 
// {ECB5BEA0-BC25-4EF7-942C-0AE8AB7FBB55} идентификатор интерфейса IDiff
DEFINE_GUID(IID_IDiff, 
    0xecb5bea0, 0xbc25, 0x4ef7, 0x94, 0x2c, 0xa, 0xe8, 0xab, 0x7f, 0xbb, 0x55);
 
// {00000000-0000-0000-C000-000000000046} идентификатор интерфейса IUnknown
DEFINE_GUID(IID_IUnknown, 
     0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
 
#define E_NOINTERFACE 0x80004002
 
typedef struct {
    int (__stdcall *QueryInterface)(void *pObject, const GUID *pInterface, void **ppOut);
    int (__stdcall *AddRef)(void *pObject);
    int (__stdcall *Release)(void *pObject);
} IUnknownVtbl;
 
typedef struct {
    IUnknownVtbl UnkVTable;
    int (__stdcall *Sum)(void *pObject, int a, int b);  // Сложить 2 числа
} ISumVtbl;
 
typedef struct {
    IUnknownVtbl UnkVTable;
    int (__stdcall *Diff)(void *pObject, int a, int b); // Вычесть 2 числа
} IDiffVtbl;
 
typedef struct {
    IUnknownVtbl* pVtbl;
} IUnknown;
 
typedef struct {
    const ISumVtbl* pVtbl;
} ISum;
 
typedef struct {
    const IDiffVtbl* pVtbl;
} IDiff;
 
// COM объект
typedef struct {
    ISum pISumVTable;    // Главный интерфейс
    IDiff pIDiffVTable;  
    long lRefCounter;    // Счетчик ссылок
} CMyComClass;
 
// Сравнить 2 GUID'а
int isGuidsEqual(const GUID *pg1, const GUID *pg2) {
    int i;
    for (i = 0; i < sizeof(*pg1) / 4; i++)
        if (((int*)pg1)[i] != ((int*)pg2)[i])
            return 0;
    return 1;
}
 
// Запрос интерфейса
int __stdcall ISum_QueryInterface(void *pObject, const GUID *pInterface, void **ppOut) {
    CMyComClass *pCls = (CMyComClass*)pObject;
 
    if (isGuidsEqual(pInterface, (GUID*)&IID_IUnknown))
        *ppOut = pObject;
    else if (isGuidsEqual(pInterface, (GUID*)&IID_ISum))
        *ppOut = pObject;
    else if (isGuidsEqual(pInterface, (GUID*)&IID_IDiff))
        *ppOut = (char*)pObject + (offsetof(CMyComClass, pIDiffVTable) - offsetof(CMyComClass, pISumVTable));
    else
        *ppOut = 0;
 
    if (*ppOut)
        pCls->lRefCounter++;
    else
        return E_NOINTERFACE;
 
    return 0;
 
}
 
int __stdcall ISum_AddRef(void *pObject) {
    CMyComClass *pCls = (CMyComClass*)pObject;
 
    return ++pCls->lRefCounter;
 
}
 
int __stdcall ISum_Release(void *pObject) {
    CMyComClass *pCls = (CMyComClass*)pObject;
 
    int lRet = --pCls->lRefCounter;
 
    if (!lRet)
        free(pCls);
 
    return lRet;
 
}
 
int __stdcall ISum_Sum(void *pObject, int a, int b) {
    return a + b;
}
 
int __stdcall IDiff_QueryInterface(void *pObject, const GUID *pInterface, void **ppOut) {
    CMyComClass *pCls = (CMyComClass*)((char*)pObject - offsetof(CMyComClass, pIDiffVTable));
 
    return pCls->pISumVTable.pVtbl->UnkVTable.QueryInterface(pCls, pInterface, ppOut);
 
}
 
int __stdcall IDiff_AddRef(void *pObject) {
    CMyComClass *pCls = (CMyComClass*)((char*)pObject - offsetof(CMyComClass, pIDiffVTable));
 
    return pCls->pISumVTable.pVtbl->UnkVTable.AddRef(pCls);
 
}
 
int __stdcall IDiff_Release(void *pObject) {
    CMyComClass *pCls = (CMyComClass*)((char*)pObject - offsetof(CMyComClass, pIDiffVTable));
 
    return pCls->pISumVTable.pVtbl->UnkVTable.Release(pCls);
 
}
 
int __stdcall IDiff_Diff(void *pObject, int a, int b) {
    return a - b;
}
 
// Инициализация виртуальных таблиц методов
const ISumVtbl ISumVTable = {ISum_QueryInterface, ISum_AddRef, ISum_Release, ISum_Sum};
const IDiffVtbl IDiffVTable = {IDiff_QueryInterface, IDiff_AddRef, IDiff_Release, IDiff_Diff};
 
// Экспортируемая функция для создания COM объекта CMyComClass
IUnknown* CreateCOMObject() {
    CMyComClass *pCls = malloc(sizeof(CMyComClass));
 
    pCls->lRefCounter = 1;
    pCls->pISumVTable.pVtbl = &ISumVTable;
    pCls->pIDiffVTable.pVtbl = &IDiffVTable;
 
    return (IUnknown*)&pCls->pISumVTable;
 
}
 
int __stdcall DllMain(void* hinstDLL, int fdwReason, void* lpvReserved) {
    return 1;
}
Для использования в VB6 сначала нужно создать библиотеку типов:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[
  uuid(DDE7D1B7-679B-4869-BE11-18D19F0520CE)
]
library TestCOM {
 
    importlib("stdole2.tlb");
 
    [
      uuid(128DAF0F-76DB-4950-9073-088A20F22265)
    ]
    interface ISum : IUnknown {
        long _stdcall Sum(long a, long b);
    }
 
    [
      uuid(ECB5BEA0-BC25-4EF7-942C-0AE8AB7FBB55)
    ]
    interface IDiff : IUnknown {
        long _stdcall IDiff(long a, long b);
    }
 
}
После компиляции COM объект прекрасно работает в VB6:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Option Explicit
 
Public Declare Function CreateCOMObject Lib "testcom" () As IUnknown
 
Sub main()
    Dim cSum    As ISum
    Dim cDiff   As IDiff
    
    ChDir App.Path
    
    Set cSum = CreateCOMObject()
    
    MsgBox cSum.Sum(10, 20)
    
    Set cDiff = cSum
    
    MsgBox cDiff.IDiff(10, 20)
 
End Sub
Подключить библиотеку dll
1
Вложения
Тип файла: rar TestCOM.rar (6.8 Кб, 6 просмотров)
991 / 217 / 21
Регистрация: 20.05.2016
Сообщений: 945
Записей в блоге: 17
06.04.2018, 08:43  [ТС] 119
The trick, познавательно. Как будет выглядеть код, если dll будет лежать в другой папке. Есть ли вариант с ранним связыванием, интересует скорость работы (будет ли она в данном примере отличатся?)
0
Модератор
8671 / 3208 / 838
Регистрация: 22.02.2013
Сообщений: 4,793
Записей в блоге: 78
06.04.2018, 12:07 120
Цитата Сообщение от bedvit Посмотреть сообщение
Как будет выглядеть код, если dll будет лежать в другой папке.
Точно также, только путь поменять в декларации и все.

Цитата Сообщение от bedvit Посмотреть сообщение
Есть ли вариант с ранним связыванием, интересует скорость работы (будет ли она в данном примере отличатся?)
А это и есть раннее связывание, позднее связывание намного сложней реализовать (для других платформ, под Windows это делается проще). Для этого нужно имплементировать IDispatch "руками". Но для сторонних платформ это не нужно, они же не поддерживают OLE Automation (или поддерживают?), раннего связывания будет достаточно.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.04.2018, 12:07

Не могу подключить dll библиотеку
Вообщем есть библиотека Visa32.dll и я не могу ее подключить. Так же есть два заголовочных файла -...

Как подключить библиотеку 7z.dll?
Как подключить библиотеку 7z.dll. Я скачал архив с сурсами, откопал 7z.dll пытаюьс добавить в...

Как подключить библиотеку i7000.dll?
у меня есть библиотека i7000.dll библиотека необходимая для работы с com портами все остальное...

Как подключить библиотеку shell32.dll ?
Решил воспользоваться примером открытия файла с помощью необходимого приложения. В примере...


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

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

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