Russian English
   Basic.net
Пятница, 29.03.2024, 08:38
Меню сайта
Категории раздела
Basic [44]
Помощь [0]
Облако тегов
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Форма входа
Главная » Статьи » Basic

Работа с DLL в Visual Basic
Share |
В данной статье описаны основные способы работы с DLL в языке программирования Visual Basic. Она поможет заинтересованному читателю ответить на ряд вопросов: что такое DLL, зачем оно нужно, как его правильно использовать и создавать.

Основы

Итак, что же такое DLL? Этой английской аббревиатурой словосочетания Dynamic-Link Library, что переводится как "динамически подключая библиотека", называют в операционных системах семейства Microsoft Windows динамические библиотеки, содержащие процедуры и функции, которые могут многократно использоваться различными программными приложениями. 

Ранние версии Windows работали в условиях жёсткого ограничения памяти, а потому использование DLL должно было позволить более активно использовать её, ведь один экземпляр DLL, загруженный в память, может использоваться сразу несколькими программами. Однако существенных преимуществ полностью получить не удалось. Причиной является такое явление, как DLL Hell ("DLL ад") - несколько программ работают с одинаковой библиотекой, однако с разными не полностью совместимыми версиями. Это приводило к большому количеству ошибок. Сейчас в Windows используется технология SxS, разрешающая параллельное использование разные версий библиотеки, что иногда сводит на нет её главное преимущество.

Тем не менее, DLL (к этому понятию также относят библиотеки ActiveX и драйверы) активно используются при разработке ПО.

Но в каких же случаях лучше использовать модули, а в каких DLL? Во-первых, модули, подключаемые к проекту, должны быть написаны на том языке, с которым работает среда разработки. DLL могут быть написаны на другом языке, хранятся они в уже откомпилированном виде. Во-вторых, использование DLL позволяет экономить память в том случае, если ею пользуются две или более программ одновременно (точнее, при использовании одной и той же версии). В-третьих, если функции не будут использоваться другими программами, то нет смысла создавать DLL. Тоже самое можно сказать про те случаи, когда нужно просто разбить для удобства большой код по модулям - удобнее работать с ними в одном проекте.

Соглашения вызова

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

Например, это расположения параметров подпрограммы: они могут быть в стеке или в регистрах. Различие существенное, от того-то эти соглашения не совместимы и нужно знать, какие используются в той или иной библиотеке. 

Существует немало разных соглашений, но из них обратим внимание на stdcall и cdecl. Первый используют библиотеки WinAPI функций. Второй же пригодиться нам для использования функций, написанных на языке Си (cdecl - C Declaration). В обоих соглашениях аргументы передаются через стек, справа налево. Но в stdcall очистку стека производит вызываемая подпрограмма, а в cdecl - вызывающая программа. 

Если что-то не поняли - не спешите ломать голову этими соглашениями, ведь для полного понимания работы с ними вам нужно знание основ Ассемблера. Не знаете? Вернетесь ещё к ним потом. 
Внимание мы уделим stdcall и cdecl. Большинство библиотек у вас будут работать и с этим.

Использование

Каким же образом использовать DLL? Как воспользоваться функциями из них? Для этого их нужно подключить к программе. Различают два способа подключения: статический и динамический.

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

Динамический. Загрузить и выгрузить DLL можно в любое время при работе программы. Преимущества: экономное использование памяти в тех случаях, когда функция используется один раз за всё время работы программы, после чего они уже не нужны. Недостатки: большее, по сравнению со статическим подключением, количество кода.

Статическое подключение

При данном способе подключения нужные функции объявляют в разделе деклараций:

Private Declare Function название_функции Lib "имя_библиотеки" Alias "название_функции_в_библиотеке" _
(ByVal параметр_1 As тип_параметра, ..., ByVal параметр_n As тип_параметра) As тип_функции

Здесь:
Declare - ключевое слово, обозначающее, что дальше следует объявление функции из библиотеки
название_функции - название функции из библиотеки, которое будет использоваться у вас в программе. Может отличаться от названия функции в самой библиотеке (см. Alias)
Lib "имя_библиотеки" - название подключаемой библиотеки. Она должна находиться в папке System32, либо вместе с исполняемым файлом
Alias "название_функции_в_библиотеке" - необязательный параметр. Используется в том случае, если имя объявляемой функции в программе отличается от имени функции в библиотеке.

Пример подключения:

Private Declare Function Symma Lib "test.dll" Alias "Summ" (ByVal a As Integer, ByVal b As Integer) As Integer

В библиотеке функция сложения двух чисел называется Summ, а у нас Symma.
Используются подключенные таким образом функции точно так же, как и обычные. Например:

c = Symma(a,b)
d = Symma(1,3)


Ну, это всё описываются библиотеки с stdcall. А как же cdecl? Ну, в VB есть ключевое слово cDecl, причём использоваться он должно так:

Private Declare Function название_функции cDecl Lib "название_библиотеки"...

Однако вероятно вы получите Bad DLL Calling Convention (Error 49). Точнее, ваша программа будет работать лишь в Native (машинном) коде, т.е. уже полностью откомпилированная. А в режиме отладки (P-код), как и в самой IDE - нет. Дальнейшая разработка программы будет очень осложнена. 
Мда, вот они какие - недокументированные возможности! Может есть шанс подключать cdecl библиотеки с динамическим подключением?

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

Как уже было сказано выше, при данном способе подключения библиотек кода будет намного больше.
Ну во-первых сразу скажу, что в Visual Basic нет возможности стандартными средствами подключать библиотеки динамическим способом.

Для этого нам нужно 3 WinAPI функции: LoadLibrary, GetProcAddress, FreeLibrary. Объявим их в разделе деклараций, а также 3 переменные, куда будем сохранять результаты:

Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" _
(ByVal lpLibFileName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" _
(ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function FreeLibrary Lib "kernel32" _
(ByVal hLibModule As Long) As Long
 
Dim handle As Long, address As Long, unload As Long

Как видите, используем мы эти функции из стандартной библиотеки kernel32.dll! Так что это статическое подключение, а значит как минимум эта библиотека у нас будет всегда в памяти.

Разберем подробнее эти функции, новые для нас. Как они работают, что делают и для чего нужны?

LoadLibrary

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

Единственный её параметр lpLibFileName (строковой тип) содержит путь либо имя подключаемой библиотеки.

Если функция завершается успешно, то она возвращает дескриптор модуля (библиотеки). Если происходит ошибка - 0.

GetProcAddress

Эта функция извлекает адрес нужной процедуры или функции из DLL.

Имеет два параметра: hModule ("хэндл", обычно целочисленный тип) и lpProcName (строковой тип). Первый параметр - дескриптор модуля. Получить его нам позволяет вышеописанная функция LoadLibrary. Второй параметр - имя нужной функции.

Если функция завершается успешно, то она возвращает адрес экспортируемой функции из модуля (библиотеки). Если происходит ошибка - 0.

FreeLibrary

Эта функция уменьшает итоговое число ссылок на DLL (если она используется одновременно несколькими приложениями), а если число ссылок становится равно 0, то выгружает библиотеку из памяти.

Имеет один параметр: hModule, т.е. дескриптор библиотеки (который, напомню, возвращает функция LoadLibrary).

Если функция завершается успешно, возвращаемой значение не равно нулю. Если происходит ошибка, то оно равно нулю.

Но основе этих функций составим программу, которая будет подключать динамически DLL (stdcall):

Option Explicit
' API-функции 
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
 
Dim handle As Long, address As Long, unload As Long ' переменные с результатами функций
 
Private Sub Form_Load()

handle = LoadLibrary("test.dll") ' загружаем библиотеку

If handle <> 0 Then ' успешная загрузка

   MsgBox ("Библиотека успешно загружена.")
   address = GetProcAddress(handle, "Summ") ' получаем адрес функции

   If address <> 0 Then ' успешное получение адреса

      MsgBox ("Адрес функции успешно получен.") ' здесь можно использовать функцию

   ElseIf address = 0 Then ' ошибка при получении адреса

      MsgBox ("Ошибка при извлечении адреса функции из DLL!")
      Exit Sub 

   End If  

ElseIf handle = 0 Then ' ошибка при загрузке 

   MsgBox ("Ошибка при загрузке DLL!")

End If 

unload = FreeLibrary(handle) ' высвобождаем библиотеку из памяти 

If unload <> 0 Then ' успешно выгрузили 

   MsgBox ("Библиотека выгружена успешно.") 

ElseIf unload = 0 Then 'ошибка при выгрузке 

   MsgBox ("Ошибка при выгрузке библиотеки из памяти!") 

End If 

End Sub
 
Как вы сами видите, длина кода намного больше, чем при статической загрузке, поскольку мы включили сюда ещё и обработку ошибок при помощи конструкции if. Налицо - гибкость!

А теперь рассмотрим возможность динамического (впрочем, как я писал выше, работать со статическим очень сложно) подключения cdecl. Для этого, кроме упомянутых выше, нам понадобятся ещё функции CallWindowProc и CopyMemory. Сразу замечу, что необходимо знание Ассемблера для полного понимания работы такой программы.

GetProcWindow

Эта функция передает информацию сообщения процедуре заданного окна. 

Имеет 5 параметров: lpFunc, который указывает на процедуру, и Param1-Param4, через которые передаются параметры функции. Все параметры имеют тип Long.

Возвращаемое значение определяет результат обработки и зависит от параметров.

RtlMoveMemory

Эта функция копирует содержимое одного блока памяти в другой.

Имеет 3 параметра: Dest - указатель в тот блок памяти, куда нужно произвести копирование, Src - указатель на тот блок памяти, который копируется, Length - количество байтов, которое должно передаваться.

Возвращаемое значение отсутствует.

В качестве примера использования мы будем вызывать функцию qsort из библиотеки ntdll.dll, написанной на Си (cdecl). Данная функция используется для быстрой сортировки массива.

Option Explicit

Private Declare Sub qsort Lib "ntdll" (base As Any, ByVal num As Long, ByVal width As Long, ByVal compare As Long)
Private Declare Function VarCmp Lib "oleaut32" (ByVal pvarLeft As Variant, ByVal pvarRight As Variant, ByVal lcid As Long, ByVal dwFlags As Long) As Long
Public Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Public Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Public Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Dest As Any, Src As Any, ByVal Length As Long)
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpFunc As Long, ByVal Param1 As Long, ByVal Param2 As Long, ByVal Param3 As Long, ByVal Param4 As Long) As Long

Dim hModule1 As Long, EntryPoint As Long
Dim hModule2 As Long, VarCmp As Long
Dim Thunk(0 To 32) As Byte
Dim Comparer(0 To 24) As Byte

Public Sub Initialize()
    hModule1 = LoadLibrary("ntdll")
    EntryPoint = GetProcAddress(hModule1, "qsort")
    hModule2 = LoadLibrary("oleaut32")
    VarCmp = GetProcAddress(hModule2, "VarCmp")
' cDecl - ложим в стек параметры справа налево
CopyMemory Thunk(0), &H102474FF, 4  'FF742410   push dword ptr [esp+10h] - помещаем адрес функции VarCmp
    CopyMemory Thunk(4), &H102474FF, 4  'FF742410   push dword ptr [esp+10h] - помещаем размер (в байтах) одной переменной
    CopyMemory Thunk(8), &H102474FF, 4  'FF742410   push dword ptr [esp+10h] - помещаем кол-во элементов массива
    CopyMemory Thunk(12), &H102474FF, 4 'FF742410   push dword ptr [esp+10h] - помещаем указатель на буфер
    CopyMemory Thunk(16), &H6E8, 2      'E806000000 call $+6 - помещаем в стек, адрес следующей инструкции,
                                        ' после вызова qSort, выполнение начнется с нее. А также вызываем
                                        ' инструкцию расположенную на шесть байт после текущей
    CopyMemory Thunk(21), &H10C483, 3   '83C410     add esp, 10h - вызов cDecl чистим стек здесь, потому что
                                        ' VB не будет этого за нами делать
    CopyMemory Thunk(24), &H10C2, 2     'C21000     ret 10h - Тоже для CallWindowProc
    Thunk(27) = &H68                    '68xxxxxxxx push xxxxxxxx - здесь пишем адрес функции qSort в стек
    CopyMemory Thunk(28), EntryPoint, 4
    Thunk(32) = &HC3                    'C3         ret - удаляем из стека адрес функции qSort, и вызываем ее
' Для косвенного вызова через qSort функции VarCmp (сравнение двух Variant переменных)
    ' qSort сама чистит стек после выполнения этой вставки.
    ' stdCall - ложим в стек параметры справа налево
Comparer(0) = &H6A                  '6A00       push 0 - dwFlags
    Comparer(2) = &H6A                  '6A00       push 0 - lcid
    CopyMemory Comparer(4), &H102474FF, 4 'FF742410 push dword ptr [esp+10h] - pvarRight
    CopyMemory Comparer(8), &H102474FF, 4 'FF742410 push dword ptr [esp+10h] - pvarLeft
    CopyMemory Comparer(12), &H2E8, 2   'E802000000 call $+2 - Начнем выполнение с Comparer(19) (push xxxxxxxx -
                                        ' где xxxxxxxx- адрес функции VarCmp)
                                        ' Возвращаемое значение в регистре eax
    Comparer(17) = &H48                 '48         dec eax  - Вычитаем единицу для соответствия константам qSort'a
    Comparer(18) = &HC3                 'C3         ret - stdcall функция VarCmp сама почистила стек, поэтому просто выходим
Comparer(19) = &H68                 '68xxxxxxxx push xxxxxxxx - здесь пишем адрес функции VarCmp в стек
    CopyMemory Comparer(20), VarCmp, 4
    Comparer(24) = &HC3                 'C3         ret - переходим к выполнению VarCmp
End Sub

Public Sub Terminate()
    FreeLibrary hModule1
    FreeLibrary hModule2
End Sub

Public Sub SystemSort(SortArray())
    Initialize
    CallWindowProc VarPtr(Thunk(0)), VarPtr(SortArray(LBound(SortArray))), UBound(SortArray) - LBound(SortArray) + 1, 16, VarPtr(Comparer(0))
    Terminate
End Sub

Sub Main()
Dim i As Long, MyArr(-800 To 4000), StartTime As Single
Randomize Timer
  For i = LBound(MyArr) To UBound(MyArr)
    MyArr(i) = Rnd * 800
  Next
StartTime = Timer
  SystemSort MyArr
  Debug.Print Round(Timer - StartTime, 4)
End Sub


Подробное описание работы - в комментариях к коду.

Альтернативный код - с CallBack функцией. В отличие от предыдущего варианта, он гибче, т.к. позволяет менять критерий сравнения, а во-вторых здесь используется CopyMemory. Вместо функции RtlMoveMemory здесь используем API-функции GetMem4, PutMem4, GetMem2.

Option Explicit
 
Private Declare Function GetMem4 Lib "msvbvm60" (pSrc As Any, pDst As Any) As Long
Private Declare Function GetMem2 Lib "msvbvm60" (pSrc As Any, pDst As Any) As Long
Private Declare Function PutMem4 Lib "msvbvm60" (pDst As Any, NewValue As Any) As Long
 
Public Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Public Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Public Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpFunc As Long, ByVal Param1 As Long, ByVal Param2 As Long, ByVal Param3 As Long, ByVal Param4 As Long) As Long
 
Dim hModule1 As Long, EntryPoint As Long
 
Dim Thunk(0 To 43) As Byte
 
Public Sub Initialize()
 
    hModule1 = LoadLibrary("ntdll")
    EntryPoint = GetProcAddress(hModule1, "qsort")
 
    ' cDecl - ложим в стек параметры справа налево
    
    Thunk(0) = &HB8                     'B800000000 - помещаем в eax адрес функции qSort
    GetMem4 EntryPoint, Thunk(1)
    Thunk(5) = &H5B                     'pop ebx
    GetMem2 &H1D89, Thunk(6)            'mov xxxxxxxx,ebx
    PutMem4 Thunk(8), Thunk(24)
    GetMem2 &HD0FF, Thunk(12)           'FFD0 - Call eax вызываем qSort
    GetMem2 &H1D8B, Thunk(14)           'mov ebx,xxxxxxxx
    PutMem4 Thunk(16), Thunk(24)
    Thunk(20) = &H53                    'push ebx
    GetMem2 &H10C2, Thunk(21)           'C21000     ret 10h - Тоже для CallWindowProc
 
    ' т.к. qSort сама чистит стек, Compare вызывается через вставку
    
    GetMem4 &H82474FF, Thunk(28)          'push   DWORD PTR [esp+0x8]  ' Дубликат параметра
    GetMem4 &H82474FF, Thunk(32)          'push   DWORD PTR [esp+0x8]  ' Дубликат параметра
    Thunk(36) = &HB8                      'mov eax,xxxxxxxx
    GetMem4 AddressOf Compare, Thunk(37)  'xxxxxxxx - Compare
    GetMem2 &HD0FF, Thunk(41)             'call eax - вызываем Compare
    Thunk(43) = &HC3                      'ret - Возвращаемся, стек почистит qSort
End Sub
 
Public Function Compare(ByVal lpOp1 As Long, ByVal lpOp2 As Long) As Long      ' CallBack - функция сравнения
    Dim Op1 As Long, Op2 As Long
    
    GetMem4 ByVal lpOp1, Op1
    GetMem4 ByVal lpOp2, Op2
    
    ' По возрастанию
    If Op1 < Op2 Then Compare = -1: Exit Function
    If Op1 = Op2 Then Compare = 0: Exit Function
    Compare = 1
    
    ' По убыванию
'    If Op1 < Op2 Then Compare = 1: Exit Function
'    If Op1 = Op2 Then Compare = 0: Exit Function
'    Compare = -1
    
End Function
 
Public Sub Terminate()
    FreeLibrary hModule1
End Sub
 
Public Sub SystemSort(SortArray() As Long)
    Initialize
    CallWindowProc VarPtr(Thunk(0)), _
                   VarPtr(SortArray(LBound(SortArray))), _
                   UBound(SortArray) - LBound(SortArray) + 1, _
                   LenB(SortArray(LBound(SortArray))), VarPtr(Thunk(28))
    Terminate
End Sub
 
Sub Main()
    Dim i As Long, MyArr(0 To 4000) As Long
    
    For i = 0 To UBound(MyArr)
        MyArr(i) = Rnd * 800
    Next
    
    SystemSort MyArr
 
End Sub


Создание

По каким-то причинам в Microsoft решили, что возможность создавать обычные DLL в Visual Basic будет лишней, а потому создавать их так просто мы не сможем, во всяком случае, без бубна. Да, я говорю про обычные DLL, потому что можно создавать лишь ActiveX DLL. В чём же разница обычных DLL от ActiveX?

ActiveX

ActiveX была внедрена в Windows компанией Microsoft в 1996 году как продолжение развития её технологий OLE (Object Linking and Embedding) и COM (Component Object Model). 

OLE - технология связи и внедрения объектов в другие документы и объекты. Она позволяет передавать данные от одной программы для редактирования другой. Так, например, изображение или рисунок в программе Microsoft Word можно редактировать в Paint, и при сохранении он автоматически измениться и в документе Word.

COM - технология создания программного обеспечения на основе взаимосвязанных компонентов. Воплощение идей объектно-ориентированного программирования (ООП): инкапсуляции и полиморфизма. 

И вот мы имеем фреймворк ActiveX, совмещающий эти две технологии. Он активно используется при разработке форм приложений. Все кнопки, списки, диалоговые окна, "этикетки" (Label), поля ввода (Textbox), их которых мы собираем форму - всё это ActiveX. Вообще многие продукты Microsoft используют управляющий элементы ActiveX, что позволяет использовать их функционал в других приложениях. Подробнее об этом смотрите в моей статье об использовании компонента Windows Media Player для создания музыкального проигрывателя.

Итак, приступим к созданию ActiveX DLL! Запускаем Visual Basic, в окне New Project выбираем ActiveX DLL (либо в меню File-New Project). И вот уже перед нами и редактор кода! Процесс написания кода здесь ничем не отличается от написания обычной программы. Пишете код, сохраняете проект, компилируете библиотеку.
Но не забывайте тот факт, что ActiveX DLL, в отличие от обычной DLL, не библиотека процедур и функций, а библиотека классов! Так что здесь забудьте про процедурное программирование - только ООП! Пишем классы: поля, свойства, методы, инкапсуляция, наследование (кстати, в Visual Basic нет обычного наследования, так что это делать нужно через наследование интерфейсов), полиморфизм. В принципе это и есть главное отличие. Хотя написать процедуру как метод не составит проблем.

Коротко об использовании ActiveX DLL. Подключаются они точно так же, как и обычные, но с той разницей, что необходимо создать объект и вызывать его методы - это называют связыванием. Различают ранее и позднее связывание.

Ранее связывание осуществляется командой

Set myObj = New имя_dll.myClass

где myObj - имя объекта, а myClass - название класса в DLL. При таком связывании вся информация о методах, свойствах и событиях класса известна во время компиляции, потому вызов методов происходит также быстро, как и обычных функций в 
программе.
При позднем связывании нужно сначала создать объект:
 
Set myObj=CreateObject("имя_dll.myClass")
 
после чего можно вызывать его метод:

x=myObj.Summ(параметры)
 
Проверка методов/свойств происходит во время выполнения программы, так что мы проигрываем раннему связыванию во времени, но зато этот способ более гибкий.

Если вас заинтересовала технология ActiveX и её возможности, рекомендую вам ознакомится со статьей Б.Л. Файфеля "COM в действии": "Создаем ActiveX DLL" и "Вопросы" (часто задаваемые вопросы про ActiveX)

Обычные DLL

Вообще-то создавать обычные DLL в Visual Basic, как уже было сказано выше, нельзя без "танцев с бубном". Но энтузиастами был создан Add-In для среды разработки Visual Basic, который позволяет создавать почти полноценные DLL на Visual Basic. Единственный, и самый существенный минус - невозможность использования созданных таким образом библиотек в других языках программирования. Загрузить Add-In можно по этой ссылке - ссылка. К архиву прилагается файл ReadMe с подробным описанием установки дополнения и его использования, а также пара примеров создания DLL.

Каким же образом мы компилируем библиотеки, если такой возможности в VB нет? Весь секрет в недокументированных возможностях link.exe ("линкеры", как известно, выполняют компиляцию в всё с этим связанное). Если запустить его в DOS командой link.exe > c:/link.txt, то мы увидим множество различных ключиков. Их них наибольший интерес представляют /DLL и /DRIVER. Понятно, что компилятор Visual Basic 6 способен ещё и компилировать библиотеки с драйверами! Ну вот именно на первом ключе и основан принцип работы этой надстройки: перехватываем командную строку линкера, изменяем, вызываем настоящий линкер.
Только одно но... это скорее не продуманная реализация линкера, а баг. Он нарушает компоновку библиотеки, из-за чего она будет работать не стабильно. А именно - лишь в Visual Basic!

Если вас заинтересовало это, то подробнее ознакомиться с работой надстройки вы можете здесь - ссылка на форум разработчиков.

Автор: Павел Смирнов  
Специально для сайта 
     basic.ucoz.net 
При публикации в СМИ
ссылка на источник и указание
авторства обязательно!

Отдельная благодарность за помощь
в написании статьи:
Catstail, SoftIce, locm, Pro_grammer,  TheTrick

Категория: Basic | Добавил: Admin (29.07.2013) | Автор: Павел Смирнов W
Просмотров: 10212 | Теги: создание dll, использование dll, dll и visual basic 6, работа с dll, activex | Рейтинг: 5.0/5
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Поиск
Наш опрос
Какую версию Basic вы предпочитаете?
Всего ответов: 2140

© Basic.ucoz.net, 2024