Форум программистов, компьютерный форум CyberForum.ru

Visual Basic

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 129, средняя оценка - 4.62
Catstail
Модератор
22142 / 10616 / 1728
Регистрация: 12.02.2012
Сообщений: 17,664
#1

Создание процедурных DLL в Visual Basic (статья) - Visual Basic

25.08.2013, 22:19. Просмотров 17152. Ответов 61
Метки нет (Все метки)

Создание процедурных DLL в Visual Basic


Несколько слов о резонах создания процедурных Dll на VB. Как известно, VB позволяет без проблем создавать ActiveX-Dll. Эта возможность в целом решает проблему повторного использования кода. Однако, есть два момента, которые могут сделать использование ActiveX-Dll (т.е. COM) не вполне удобным.

Первая проблема состоит в том, что ActiveX-Dll нельзя просто скопировать - нужна регистрация (т.е. административные права). А при повсеместном внедрении политик безопасности, получение прав администратора вырастает в большую проблему. Использование процедурных dll не требует регистрации.

Вторая проблема состоит в том, что интенсивное использование кода из ActiveX-Dll (даже при раннем связывании) все-таки медленнее, чем использование кода из своей программы (или из процедурной dll) - ведь соблюдение стандарта COM требует ресурсов... И особенно больших, если используется ActiveX-Exe.

Все это делает создание процедурных dll на VB достаточно актуальным.

Теперь к делу!

Интересующиеся деталями могут прочитать мой перевод статьи
"Создание процедурных DLL в Visual Basic".

А для "занятых" могу сказать следующее:

1) Скопируйте и разверните прилагаемый архив с примерами
2) из поддиректории link-2 возьмите модуль linkk.exe; перенесите его в установочную директорию VB (она обычно располагается по адресу \Program Files\Microsoft Visual Studio\Vb98); модуль LINK.EXE переименуйте в LINKLNK.EXE,
а модуль linkk.exe -> LINK.EXE
3) Для создание dll действуйте так:

- создавайте проект ActiveX-DLL (и назовите myLib)
- модуль класса не трогайте
- добавьте в проект стандартный модуль и занесите в него следующее:

Visual Basic
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
Public Const DLL_PROCESS_DETACH = 0
Public Const DLL_PROCESS_ATTACH = 1
Public Const DLL_THREAD_ATTACH = 2
Public Const DLL_THREAD_DETACH = 3
 
Public lastErr As Long
 
Public Function DllMain(hInst As Long, fdwReason As Long, _
  lpvReserved As Long) As Boolean
   Select Case fdwReason
      Case DLL_PROCESS_DETACH
         ' при завершении процесса ничего не делать…
      Case DLL_PROCESS_ATTACH
         DllMain = True
      Case DLL_THREAD_ATTACH
         ' перед началом потока ничего не делать…
      Case DLL_THREAD_DETACH
         ' после завершения потока ничего не делать
   End Select
End Function
 
Public Function Increment(var As Integer) As Integer
   Increment = var + 1
End Function
 
Public Function Decrement(var As Integer) As Integer
   Decrement = var - 1
End Function
 
Public Function Square(var As Long) As Long
   On Error Resume Next
   Square = var ^ 2
   If Err.Number <> 0 Then lastErr = Err.Number
End Function
 
Public Function getLastError() As Long
   getLastError = lastErr
End Function
 
Public Function ClearError() As Long
   lastErr = 0
End Function
- создайте текстовый файл myLib.def:


NAME myLib
LIBRARY MathMod
DESCRIPTION "... ..."
EXPORTS DllMain @1
Increment @2
Decrement @3
Square @4
getLastError @5
ClearError @6


- транслируйте проект обычным образом в среде IDE - получится процедурная DLL!

Для проверки работспособности DLL можно написать отдельный тестирующий модуль, в котором написать нужные операторы Declare для использования наших функций.

Все, разложенные по директориям, исходники прилагаются:
Вложения
Тип файла: zip vb_dll_proc.zip (27.2 Кб, 217 просмотров)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
25.08.2013, 22:19     Создание процедурных DLL в Visual Basic (статья)
Посмотрите здесь:

Visual Basic Создание приложения в среде Visual Basic
Visual Basic Создание приложения в среде Visual Basic
Visual Basic Создание игры на Visual Basic-е
Visual Basic создание dll на основе visual basic
Visual Basic Можно ли в Visual Basic использовать стандартные Windows DLL?
Visual Basic + VC++ DLL = ошибка Bad DLL calling convertation Visual Basic
Где бесплатно скачать учебник по Visual Basic 6 и Visual Basic .Net ? Visual Basic
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Catstail
Модератор
22142 / 10616 / 1728
Регистрация: 12.02.2012
Сообщений: 17,664
25.08.2013, 22:26  [ТС]     Создание процедурных DLL в Visual Basic (статья) #2
Файл .def нужно создавать в директории проекта
Dragokas
Эксперт WindowsАвтор FAQ
14898 / 6501 / 792
Регистрация: 25.12.2011
Сообщений: 10,042
Записей в блоге: 14
25.08.2013, 22:55     Создание процедурных DLL в Visual Basic (статья) #3
Борис, спасибо
Замечательный перевод, читается легко, все коротко и понятно.
Подмена аргументов - самый безболезненный способ.
Протестировал на Windows 7x64 и 8x64. Работает без ошибок.

При чем объявлять библиотеки можно без полного пути. Вот так:

Visual Basic
1
Private Declare Function Increment Lib "MathLib.dll" (var As Integer) As Integer
Работает при переносе в другую папку и даже если запустить с повышенными правами, несмотря на то, что рабочий каталог должен изменяться на %windir%\system32 - линкер все берет на себя и собирает правильно.
Catstail
Модератор
22142 / 10616 / 1728
Регистрация: 12.02.2012
Сообщений: 17,664
26.08.2013, 08:26  [ТС]     Создание процедурных DLL в Visual Basic (статья) #4
Хотелось бы отметить собственное упущение - весь материал основан на статье (автор: R. Petrusha; опубликована в 2005 г.; в переводе статьи есть ссылка на оригинал). Мой "вклад в проблему" - только перевод и небольшое дополнение в конце (касающееся обработки ошибок).
locm
1970 / 725 / 68
Регистрация: 28.10.2011
Сообщений: 2,119
Записей в блоге: 2
26.08.2013, 17:11     Создание процедурных DLL в Visual Basic (статья) #5

Не по теме:

Теперь еще осталось разобраться как на VB создавать драйверы.



Добавлено через 17 минут
Кстати, из другого ЯП функции библиотеки корректно не выполняются.
Что этот код.
PureBasic
1
2
3
4
5
Prototype Increment(x)
If OpenLibrary(0, "mathlib.dll")
  Increment.Increment = GetFunction(0, "Increment")
  Debug Increment(2)
EndIf
Что этот.
PureBasic
1
2
3
4
If OpenLibrary(0, "mathlib.dll")
  Debug CallFunction(0, "Increment", 2)
EndIf
End
Выдают ошибку: "Невозможен доступ к памяти (ошибка чтения по адресу 2)".
Pro_grammer
Модератор
5858 / 2018 / 385
Регистрация: 24.04.2011
Сообщений: 3,426
Записей в блоге: 9
26.08.2013, 20:19     Создание процедурных DLL в Visual Basic (статья) #6
Цитата Сообщение от locm Посмотреть сообщение
"Невозможен доступ к памяти (ошибка чтения по адресу 2)".
Видно, что передаете в функцию число 2 по значению , а в функции обрабатывается ссылка на память по адресу 2.
Надо функции DLL подкорректировать и передавать в функцию указатель на переменную, типа @2, тогда может что и выйдет.
locm
1970 / 725 / 68
Регистрация: 28.10.2011
Сообщений: 2,119
Записей в блоге: 2
26.08.2013, 21:08     Создание процедурных DLL в Visual Basic (статья) #7
Цитата Сообщение от Pro_grammer Посмотреть сообщение
Видно, что передаете в функцию число 2 по значению , а в функции обрабатывается ссылка на память по адресу 2.
С другими DLL, в т. ч. системными это нормально работает.
Craw
234 / 45 / 4
Регистрация: 10.06.2012
Сообщений: 268
Записей в блоге: 1
28.08.2013, 15:16     Создание процедурных DLL в Visual Basic (статья) #8
Всё хорошо, только вот опять столкнулись с той же проблемой, что и в вариант в моей статье - не выходит использовать в других ЯП. У locm не вышло в Basic4GL, а у меня в Delphi:

Delphi
1
2
3
4
5
6
7
var
  function Increment (x : integer) : integer; stdcall; external 'MathLib.dll';
 
procedure TForm1.Button1Click(Sender: TObject);
begin
   Edit1.Text := IntToStr(Increment(StrToInt(Edit1.Text)));
end;
В итоге ошибка EAccessViloation, адрес 110019В4 (2 строка):


Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
110019B0 8B442404         mov eax,[esp+$04]
110019B4 668B00           mov ax,[eax]
110019B7 66050100         add ax,$0001
110019BB 7003             jo +$03
110019BD C20400           ret $0004
110019C0 FF155C100011     call dword ptr [$1100105c]
110019C6 90               nop 
110019C7 90               nop 
110019C8 90               nop 
110019C9 90               nop 
110019CA 90               nop 
110019CB 90               nop 
110019CC 90               nop 
110019CD 90               nop 
110019CE 90               nop 
110019CF 90               nop
locm
28.08.2013, 16:15
  #9

Не по теме:

Цитата Сообщение от Craw Посмотреть сообщение
У locm не вышло в Basic4GL
Это не Basic4GL. Это такой тупой тег, который все бейсики причисляет к Basic4GL.

Craw
234 / 45 / 4
Регистрация: 10.06.2012
Сообщений: 268
Записей в блоге: 1
28.08.2013, 17:11     Создание процедурных DLL в Visual Basic (статья) #10
Цитата Сообщение от Pro_grammer Посмотреть сообщение
Видно, что передаете в функцию число 2 по значению , а в функции обрабатывается ссылка на память по адресу 2.
Так-с, я попробовал передавать функции не число, а указатель на переменную с этим числом, следуя вашему совету.
В итоге получился такой код:
Delphi
1
2
3
4
5
6
7
8
9
  function Increment (x : PInteger) : integer; stdcall; external 'MathLib.dll';
...
procedure TForm1.Button1Click(Sender: TObject);
var
   y : integer; // Г§Г*Г*Г·ГҐГ*ГЁГҐ Edit1
begin
   y:=StrToInt(Edit1.Text);
   Edit1.Text:=IntToStr(Increment(@y));
end;
В итоге мне удалось успешно запустить программу и вызвать функцию, так что следует искать в этом направлении.
Успешно - с той оговоркой, что функция прибавила единицу не к передаваемому значению (например х=1), а к адресу этого значения, в результате вместо 1+1=2 я получил число 1179650 (т.е. 1179649 - адрес переменной х).
Думаю, нужно просто переделать пример для работы с указателями, и у нас будет почти полноценная DLL. Почти - потому что только указатели.
skMaster
3 / 3 / 2
Регистрация: 26.02.2013
Сообщений: 39
Завершенные тесты: 1
16.11.2013, 13:54     Создание процедурных DLL в Visual Basic (статья) #11
Ктонибудь сталкивался с такой проблемой:

1) Делаю DLL как описано выше
2) С помощью CFF Explorer добавляю в "левое" приложение импорт DLL-ки
3) Запускаю "левое" приложение
Результат: Ноль реакции! DllMain не вызывается!

А если делаю DLL на C++ то все нормально вызывается "левым" приложением!
Может я что делаю нетак, помогите плиз!
Pro_grammer
Модератор
5858 / 2018 / 385
Регистрация: 24.04.2011
Сообщений: 3,426
Записей в блоге: 9
16.11.2013, 14:58     Создание процедурных DLL в Visual Basic (статья) #12
Цитата Сообщение от skMaster Посмотреть сообщение
Запускаю "левое" приложение
А оно на каком ЯП написано?
Потому, что если читали всю тему, то "не выходит использовать в других ЯП DLL, созданные в VB6!"
Если у вас современный ЯП, который поддерживает COM, OCX, то надо воспользоваться именно этими возможностями.
skMaster
3 / 3 / 2
Регистрация: 26.02.2013
Сообщений: 39
Завершенные тесты: 1
16.11.2013, 20:31     Создание процедурных DLL в Visual Basic (статья) #13
Тему я всю прочитал. "левое" приложение написано не на ВБ. На чем именно я даже и не разбирался. Смутил просто пост:
Цитата Сообщение от Craw Посмотреть сообщение
В итоге мне удалось успешно запустить программу и вызвать функцию, так что следует искать в этом направлении.
Вот и думал может решение уже роддилось, и просто у меня невыходит правильно организовать импорт!
Craw
234 / 45 / 4
Регистрация: 10.06.2012
Сообщений: 268
Записей в блоге: 1
17.11.2013, 21:00     Создание процедурных DLL в Visual Basic (статья) #14
Цитата Сообщение от skMaster Посмотреть сообщение
Смутил просто пост
В самом VB6 работать с этими DLL можно без особых проблем, а вот в других ЯП у нас так и не получилось нормально подключить библиотеку. Программа просто не запускается, либо появляется ошибка при вызове функции из библиотеки.

Цитата Сообщение от skMaster Посмотреть сообщение
Вот и думал может решение уже роддилось
В ходе экспериментов (в Delphi) мне удалось запустить функцию - я подавал на вход не саму переменную (значение), а её адрес в памяти (указатель). И я сделал вывод, что если переделать всю DLL на работу с указателями, то, возможно, всё получиться. Так что, возможно, решение уже есть, дерзайте и проверьте!
locm
1970 / 725 / 68
Регистрация: 28.10.2011
Сообщений: 2,119
Записей в блоге: 2
17.11.2013, 21:07     Создание процедурных DLL в Visual Basic (статья) #15
Мое ИМХО.
VB хорошо подходит для ActiveX-Dll, но для обычных, как говорится "овчинка выделки не стоит". Слишком уж много "если" при разработке такой DLL. Возможно стоит использовать более подходящий инструмент для этого.
Craw
234 / 45 / 4
Регистрация: 10.06.2012
Сообщений: 268
Записей в блоге: 1
18.11.2013, 00:14     Создание процедурных DLL в Visual Basic (статья) #16
Цитата Сообщение от locm Посмотреть сообщение
VB хорошо подходит для ActiveX-Dll, но для обычных, как говорится "овчинка выделки не стоит".
С этим никто не спорит - универсальных языков нет, каждый предназначен для конкретно своей области.

И все наши попытки "танцев с бубном" для реализации нереализуемого, кажется, направлены не на результат, а на сам процесс "танцев"? Ведь практического значения здесь мало всё равно, но теоретически мы доказали эту возможность.
Pro_grammer
Модератор
5858 / 2018 / 385
Регистрация: 24.04.2011
Сообщений: 3,426
Записей в блоге: 9
18.11.2013, 00:20     Создание процедурных DLL в Visual Basic (статья) #17
Цитата Сообщение от Craw Посмотреть сообщение
мы доказали эту возможность.
Пока рабочего примера не видел.
Craw
234 / 45 / 4
Регистрация: 10.06.2012
Сообщений: 268
Записей в блоге: 1
18.11.2013, 15:43     Создание процедурных DLL в Visual Basic (статья) #18
Цитата Сообщение от Pro_grammer Посмотреть сообщение
Пока рабочего примера не видел.
Цитата Сообщение от Craw Посмотреть сообщение
В итоге мне удалось успешно запустить программу и вызвать функцию, так что следует искать в этом направлении.
Успешно - с той оговоркой, что функция прибавила единицу не к передаваемому значению (например х=1), а к адресу этого значения, в результате вместо 1+1=2 я получил число 1179650 (т.е. 1179649 - адрес переменной х).
Рабочий пример на Delphi есть. Программа и функция успешно запускаются и работают, возвращая число (хоть и неправильное).
Ведь до этого, напомню, не запускалась вообще! А так возможность загрузки библиотеки и успешной работы функции теоретически доказана. Не практически - потому что нужно саму библиотеку под указатели переделать.
Pro_grammer
Модератор
5858 / 2018 / 385
Регистрация: 24.04.2011
Сообщений: 3,426
Записей в блоге: 9
18.11.2013, 16:28     Создание процедурных DLL в Visual Basic (статья) #19
Цитата Сообщение от Craw Посмотреть сообщение
функция успешно запускаются и работают, возвращая число (хоть и неправильное).
Цитата Сообщение от Craw Посмотреть сообщение
возможность загрузки библиотеки и успешной работы функции теоретически доказана.
Ну да, это как в старом анекдоте, член есть, но не стоит
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.11.2013, 15:14     Создание процедурных DLL в Visual Basic (статья)
Еще ссылки по теме:

Visual Basic Способы передачи данных с Visual Basic в Excel (статья)
Visual Basic 6 DLL для работы с php файлами Visual Basic
Visual Basic Работа с DLL в Visual Basic (статья)
Visual Basic Visual Basic вылетает с ошибкой при попытке вызова функции из DLL
Вычисление значений функции двух переменных в Visual Basic - Visual Basic Visual Basic

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

Или воспользуйтесь поиском по форуму:
locm
1970 / 725 / 68
Регистрация: 28.10.2011
Сообщений: 2,119
Записей в блоге: 2
20.11.2013, 15:14     Создание процедурных DLL в Visual Basic (статья) #20
Дизассемблировал DLL. Код функции Increment.
Assembler
1
2
3
4
5
6
 Increment:
        mov eax,[esp+04h]
        mov ax,[eax]
        add ax,0001h
        jo  L110019C0
        retn    0004h
Каким он должен быть в стандартной DLL (функция с типом вызова stdcall).
Assembler
1
2
3
4
5
6
7
 Increment:
        push    ebx
        mov ebx,[esp+08h]
        inc ebx
        mov eax,ebx
        pop ebx
        retn    0004h
Добавлено через 6 минут
Рабочий код вызова функции из VB DLL.
PureBasic
1
2
3
4
5
6
7
Prototype.u Increment(x)
If OpenLibrary(0, "mathlib.dll")
  Increment.Increment = GetFunction(0, "Increment")
  x=2
  y.u=Increment(@x)
  Debug y
EndIf
Yandex
Объявления
20.11.2013, 15:14     Создание процедурных DLL в Visual Basic (статья)
Ответ Создать тему
Опции темы

Текущее время: 15:54. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru