Динамическое подключение DLL

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Thyeadeschatarr
Начинающий
Начинающий
Аватара пользователя
 
Сообщения: 4
Зарегистрирован: 18.09.2008 (Чт) 8:26

Динамическое подключение DLL

Сообщение Thyeadeschatarr » 18.09.2008 (Чт) 9:50

Здравствуйте!

Есть у меня такая задача:
Моя библиотечка на VB использует функции из библиотечки, писанной на Delphi.
Сейчас все выглядит очень просто, примерно так:
Код: Выделить всё
Declare Function MyFunc Lib "C:\Program Files\MyTools\MyDLL.dll" (ByVal s As String) As String

Проблема в том, что путь к MyDLL.dll может быть иным - куда пользователь поставит. При установке путь пишется в реестр, прочитать я его могу, но вот как подключить функцию в процессе исполнения кода - найти не удалось. Подскажите, пожалуйста.

HiSER
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 88
Зарегистрирован: 04.07.2007 (Ср) 18:17

Re: Динамическое подключение DLL

Сообщение HiSER » 18.09.2008 (Чт) 11:13

А не проще так:
Код: Выделить всё
Declare Function MyFunc Lib "MyDLL.dll" (ByVal s As String) As String

Библеотека тогда должна находиться вместе с программой либо в %SystemRoot%\System32

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Динамическое подключение DLL

Сообщение Хакер » 18.09.2008 (Чт) 11:38

Подсказываю.

Способ 1. Не выходя на замки Declare.
Перед самым первым (хронологически) вызовом функции из DLL: установить её путь в качестве текущего (с помощью ChDir, ChDrive) вызвать функцию, после чего вернуть оригиналное значение CurDir. В дальнейшем можно вызывать функции как обычно.

Т.е., скажем, библиотека называется TestDll, а путь к ней лежит в переменной TestPath:
Загвоздка в том, что надо помнить о текущих папках, о том, что у каждого тома она своя.
Код: Выделить всё
Declare Sub SomeDummyFunctionFromTestDll Lib "TestDll.dll" ()
...

Public Sub LoadMyDll()
Dim sCurDir As String
Dim sCurDrive As String

    sCurDrive = Left$(CurDrive, 2)
    ChDrive Left$(TestPath, 2)
    sCurDir = CurDir
    ChDir TestPath

     SomeDummyFunctionFromTestDll          ' Один этот вызов заставит библиотеку загрузиться

     ChDir sCurDir
     ChDrive sCurDrive
End Sub


После этого остальные функции можно вызывать без всякой мороки. Также в этом коде стоило бы сделать проверку на ошибки 53 (File not found) и 453 (Can't find entry point ...).

Способ 2. Не выходя за рамки Declare, но выходя за рамки VB.
Его можно использовать, если не только путь, но и имя файла библиотеки заранее неизвестно. Или если не нравятся манипуляции с текущей папкой.
Суть заключается в следующем:
Вместо имени файла DLL указывается некая метка, заведомо не являющаяся путем. Лучше чтобы она была уникальной. Для этого можно например использовать UUID, но я буду использовать {MyCoolDllFileName}.

Код: Выделить всё
Declare Function SomeA Lib "{MyCoolDllFileName}" (...) As ...
Declare Function SomeAbc Lib "{MyCoolDllFileName}" (...) As ...
Declare Function SomeDef Lib "{MyCoolDllFileName}" (...) As ...
Declare Function SomeEgEg995 Lib "{MyCoolDllFileName}" (...) As ...
Declare Function StartBaCaDa Lib "{MyCoolDllFileName}" (...) As ...



При этом, в самом начале (до самого первого вызова из библиотеки) нужно перехватить функцию kernel32!LoadLibraryA. При перехвати, нужно сравнить переданный пусть с "{MyCoolDllFileName}", и если переданный пусть совпал с "{MyCoolDllFileName}", то заменить его на треюуемый путь. При этом код перехвата может (и даже должен) снять перехват, поскольку больше он не требуется.

Можно таким же образом перехватывать msvbvm60!DllFunctionCall, но во-первых тебе будет сложнее, а во-вторых, работало бы только в скомпилированном варианте.

Способ 3. Выходя за рамки Declare
Просто вызывать по указателю с помощью LoadLibrary+GetProcAddress
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Re: Динамическое подключение DLL

Сообщение Viper » 18.09.2008 (Чт) 11:59

Thyeadeschatarr писал(а):Проблема в том, что путь к MyDLL.dll может быть иным - куда пользователь поставит. При установке путь пишется в реестр, прочитать я его могу, но вот как подключить функцию в процессе исполнения кода - найти не удалось. Подскажите, пожалуйста.
А с какго перепуга пользователь может поставить DLL куда ему хочется? Не должно такого быть. Есть вполне четкая последовательность поиска DLL при ее загрузке. Поиск производится в директории из которой запущено приложение, в текущей директории, в системной директории, в директории Windows и в директориях прописанных в переменной среды PATH.
Весь мир матрица, а мы в нем потоки байтов!

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Динамическое подключение DLL

Сообщение Хакер » 18.09.2008 (Чт) 12:07

Viper, мало ли — может у него там гибкая система плагинов, где каждый плагин может быть установлен в своей какой-то папке.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Re: Динамическое подключение DLL

Сообщение Viper » 18.09.2008 (Чт) 13:24

Хакер писал(а):Viper, мало ли — может у него там гибкая система плагинов, где каждый плагин может быть установлен в своей какой-то папке.
Ну в принципе да. Хотя тоже не стоит плагины по разным углам кидать.
Весь мир матрица, а мы в нем потоки байтов!

Thyeadeschatarr
Начинающий
Начинающий
Аватара пользователя
 
Сообщения: 4
Зарегистрирован: 18.09.2008 (Чт) 8:26

Re: Динамическое подключение DLL

Сообщение Thyeadeschatarr » 19.09.2008 (Пт) 7:48

2 Хакер: Спасибо большое, способы 1 и 3 пригодятся. Второй мне как-то кажется наименее красивым, хотя, может, я чего-то недопонимаю в нем.
2 Viper: Использумая мной библиотека является частью другого программного продукта. Конечно, вероятность того, что пользователь при установке будет менять путь по умолчанию мала, но я не редко видел что система, а с ней и Program Files, стоит не на диске C. Моя же dll просто связывает между собой два продукта )

sosed213
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 206
Зарегистрирован: 13.11.2007 (Вт) 21:19
Откуда: Омск

Re: Динамическое подключение DLL

Сообщение sosed213 » 06.03.2021 (Сб) 10:20

Столкнулся с проблемой при использовании dll, если путь сетевой.

Допустим программа запускается из сетевой шары (\\server\soft\test\).
Если запуск происходит первый раз, то обращение к библиотеке происходит нормально.

Код: Выделить всё
' Пример объявления функции
Public Declare Function wimlib_global_cleanup CDecl Lib "libwim-15.dll" () As Long


Но после использования GetOpenFileName, переменная CurDir запоминает другой путь, и уже при следующем запуске моей программы, вылетает ошибка 53, т.к. программа ищет библиотеку по другому пути.

Собственно вопрос, как можно CurDir изменить на app.path?

Скорее всего как то через копирование памяти в адрес CurDir?
Не могу сказать что знаю все, но и за дурака прошу меня не считать.

sosed213
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 206
Зарегистрирован: 13.11.2007 (Вт) 21:19
Откуда: Омск

Re: Динамическое подключение DLL

Сообщение sosed213 » 06.03.2021 (Сб) 10:39

Разобрался сам.
Получилось так:

Код: Выделить всё
Public Declare Function SetCurrentDirectoryW Lib "kernel32" (ByVal lpPathName As Long) As Long

Dim apppath As String
apppath = App.Path

Debug.Print CurDir
Debug.Print SetCurrentDirectoryW(ByVal StrPtr(apppath))
Debug.Print CurDir
Не могу сказать что знаю все, но и за дурака прошу меня не считать.


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex-бот и гости: 47

    TopList