Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в эту темуОткрыть новую тему
> [PureBasic] Пример плагина, Пример простого плагина для UO Pilot на языке PureBasic
Linker
сообщение 15.6.2022, 17:07
Сообщение #1


*

Registred
Сообщений: 3
Регистрация: 15.6.2022
Группа: Пользователи
Наличность: 0
Пользователь №: 20.281
Возраст: 30



Пример плагина на одном из самых простых языков - бейсике.
Код
Код
#CountFunct = 4; Число фукнций плагина.

Structure InitStruct
  FunctionCount.l
  Array FunctionNames.s(#CountFunct-1)
EndStructure

Structure ParamStruct
  WindowHandle.i
  WindowPID.i
  Reserved.i
  ParamString.s
  ParamStringOrig.s
  Result.s{1048576}
EndStructure

EnableExplicit; Обязательная декларация переменных.

Global InitStruct.InitStruct

ProcedureDLL InitPlugin(App, Scr, *Version.Double)
  
  With InitStruct
    If *Version\d >= 2.37
      \FunctionCount = #CountFunct
      \FunctionNames(0) = "Function1"; Имена экспортируемых фунукций плагина.
      \FunctionNames(1) = "Function2"
      \FunctionNames(2) = "Function3"
      \FunctionNames(3) = "Function4"
    Else
      \FunctionCount = 0;
      *Version\d = 2.37
    EndIf
  EndWith
  
  ProcedureReturn InitStruct
EndProcedure

ProcedureDLL Function1(*ParamStruct.ParamStruct)
  Protected r
  r=Val(StringField(*ParamStruct\ParamString, 1, ",")) + Val(StringField(*ParamStruct\ParamString, 2, ","))
  *ParamStruct\Result = "Param1 + Param2 = " + r
EndProcedure

ProcedureDLL Function2(*ParamStruct.ParamStruct)
  *ParamStruct\Result = "Выполнена функция 2"
EndProcedure

ProcedureDLL Function3(*ParamStruct.ParamStruct)
  *ParamStruct\Result = "Выполнена функция 3"
EndProcedure

ProcedureDLL Function4(*ParamStruct.ParamStruct)
  *ParamStruct\Result = "Выполнена функция 4"
EndProcedure

ProcedureDLL DonePlugin()
EndProcedure
Код довольно прост и основан на примере из справки.
Чтобы процедура была доступна вне dll ее нужно объявлять с DLL в конце ключевого слова, т. е. ProcedureDLL.
Первая фукнция (Function1) складывает числа переданные в 2 параметрах и возращает результат. Остальные только сообщают номер своей фукнции.

Для компиляции необходима среда программирвоания PureBasic версии не выше 5.24. В версиях новее
выпилен ascii (остался только юникод, который не поддерживает UO Pilot). Из-за чего код будет сложнее из-за необходимости конвертирования с ascii в unicode иобратно.
Скачать версию 5.24 https://www.upload.ee/files/14232929/PureBa...Win_x86.7z.html
Это portable версия и после распаковки архива готова к работе. Запускается с помощью PureBasic Portable.exe
В редактор кода нужно скопировать исходник dll и открыть окно настроек компилятора из меню Компилятор -> Настроки компилятора. В нем выбрать формт исполняемого файла "Shared dll". Настройки сохранятся в исходнике на текущей вкладке.
После скомпилировать dll через меню Компилятор -> Создать приложение.

Прикрепленное изображение

Тестовый скрипт
Код
Msg PB_Plug.Function1(2, 8)
Msg PB_Plug.Function2()
Msg PB_Plug.Function3()
Msg PB_Plug.Function4()
exit


Прикрепленные файлы
Прикрепленный файл  PB_TestPlugin.7z ( 4,7 килобайт ) Кол-во скачиваний: 115
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
Cockney
сообщение 16.6.2022, 10:54
Сообщение #2


********

Master
Сообщений: 1.394
Регистрация: 22.6.2013
Группа: Пользователи
Наличность: 20894
Пользователь №: 16.156



Тут стоит оставить комментарий о том, что этот плагин будет работать со "старым" пилотом, до интеграции с луа. В новых версиях такой тип плагинов вряд-ли будет работать без проблем.

Для новых версий в плагинах можно не использовать InitStruct и ParamStruct, а писать напрямую как обычные функции:

Код

int func1(int a, int b) {
   return a + b;
}



А в самом пилоте нужно объявить эту функцию:

Код

ffi.cdef[[
    int func1(int a, int b);
]]


И далее использовать:

Код

local res = mylib.func1(10, 10)
Пользователь в онлайне!Delete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
Linker
сообщение 16.6.2022, 11:43
Сообщение #3


*

Registred
Сообщений: 3
Регистрация: 15.6.2022
Группа: Пользователи
Наличность: 0
Пользователь №: 20.281
Возраст: 30



Цитата(Cockney @ 16.6.2022, 10:54) *
В новых версиях такой тип плагинов вряд-ли будет работать без проблем.
Какие возможны проблемы?
Я не нашел описания плагинов. Единственное что есть это два кода (на Си и паскале) в uopilot без каких-либо пояснений и несколько обсуждений на этом форуме.
Нет никаких пояснений как передаются параметры в функцию и как возвращаются. Пришлось выяснять экспериментально.

Цитата(Cockney @ 16.6.2022, 10:54) *
Для новых версий в плагинах можно не использовать InitStruct и ParamStruct, а писать напрямую как обычные функции
Судя по примерам где вызываются функции из системных dll винды, эти плагины ничем не отличаются от обычных dll. То есть это не специально написанные плагины для пилота.
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
Cockney
сообщение 16.6.2022, 11:53
Сообщение #4


********

Master
Сообщений: 1.394
Регистрация: 22.6.2013
Группа: Пользователи
Наличность: 20894
Пользователь №: 16.156



Цитата(Linker @ 16.6.2022, 11:43) *

Какие возможны проблемы?
Я не нашел описания плагинов. Единственное что есть это два кода (на Си и паскале) в uopilot без каких-либо пояснений и несколько обсуждений на этом форуме.
Нет никаких пояснений как передаются параметры в функцию и как возвращаются. Пришлось выяснять экспериментально.

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


Код примеров на C и Паскале это пример старой системы плагинов, т.е. нормально она будет работать если используется только язык пилота, а если использовать язык lua, то уже вряд ли. Как минимум нужно специально обрабатывать структуры InitStruct, ParamStruct.

DLL которая использует InitStruct, ParamStruct по сути прибита гвоздями к пилоту. Вызвать в любом стороннем приложении ее будет проблемно (нужно обрабатывать InitStruct, ParamStruct).

В качестве референса оставлю ссылку на примет плагина на C# https://forum.uokit.com/index.php?showtopic=69767

Код там простой и, думаю, ответит на вопросы, если они возникнут. Ключевое, что там не используется InitStruct, а это дает возможность вызывать плагин не только из пилота без проблем.
Пользователь в онлайне!Delete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
DarkMaster
сообщение 16.6.2022, 12:56
Сообщение #5


***********

Модератор UOPilot
Сообщений: 9.460
Регистрация: 2.12.2008
Группа: Супермодераторы
Наличность: 27707
Пользователь №: 11.279



Сейчас действительно проще линковать через ffi, т.к. там нет почти никаких ограничений. Если есть какие-то вопросы по части, как все это работает - спрашивайте, объянсим так подробно, насколько это необходимо.


--------------------
Скрипты UOPilot под заказ.
Консультации по UOpilot 15$/час.
Услуги Lua разработчика (не пилот, проекты, постоянка)
Disсоrd:
Kov____
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
Linker
сообщение 16.6.2022, 13:02
Сообщение #6


*

Registred
Сообщений: 3
Регистрация: 15.6.2022
Группа: Пользователи
Наличность: 0
Пользователь №: 20.281
Возраст: 30



Цитата(Cockney @ 16.6.2022, 11:53) *
В качестве референса оставлю ссылку на примет плагина на C#
C# создает библиотеку классов...
Создание процедурной требует сторонние инструменты и много лишнего в коде.
ИМХО так код выглядит проще
Код
Код
Structure ArrI
  i.i[0]
EndStructure

ProcedureDLL.s Hello(arg.s)
  Static r.s
  r = "Hello " + arg
  ProcedureReturn r
EndProcedure

ProcedureDLL RGB_Func(r, g, b)
  ProcedureReturn RGB(r, g, b)
EndProcedure

ProcedureDLL mymul(argc, *args.ArrI)
  r=1
  
  If *args
    For i=0 To argc-1
      r * *args\i[i]
    Next
  EndIf
  
  ProcedureReturn r
EndProcedure

ProcedureDLL fill(size, *mem.ArrI)
  
  For i=0 To size-1
    *mem\i[i] = Random($7FFFFFFF)
  Next
  
EndProcedure



Прикрепленные файлы
Прикрепленный файл  Plug.7z ( 4,92 килобайт ) Кол-во скачиваний: 117
Пользователь в офлайнеDelete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения
Cockney
сообщение 16.6.2022, 13:43
Сообщение #7


********

Master
Сообщений: 1.394
Регистрация: 22.6.2013
Группа: Пользователи
Наличность: 20894
Пользователь №: 16.156



Цитата(Linker @ 16.6.2022, 13:02) *

C# создает библиотеку классов...
Создание процедурной требует сторонние инструменты и много лишнего в коде.
ИМХО так код выглядит проще
Код
Код
Structure ArrI
  i.i[0]
EndStructure

ProcedureDLL.s Hello(arg.s)
  Static r.s
  r = "Hello " + arg
  ProcedureReturn r
EndProcedure

ProcedureDLL RGB_Func(r, g, b)
  ProcedureReturn RGB(r, g, b)
EndProcedure

ProcedureDLL mymul(argc, *args.ArrI)
  r=1
  
  If *args
    For i=0 To argc-1
      r * *args\i[i]
    Next
  EndIf
  
  ProcedureReturn r
EndProcedure

ProcedureDLL fill(size, *mem.ArrI)
  
  For i=0 To size-1
    *mem\i[i] = Random($7FFFFFFF)
  Next
  
EndProcedure




Да хоть COM объектов. Это не меняет сути того что завязка на Init(Param)Struct не нужна больше, если не требуется совместимость со старыми версиями.
Пользователь в онлайне!Delete PostОтправить личное сообщение
Вернуться в начало страницы
+Ответить с цитированием данного сообщения

Ответить в эту темуОткрыть новую тему
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 

- Текстовая версия | Версия для КПК Сейчас: 29.3.2024, 13:03
Designed by Nickostyle