Оберон-клуб «ВЄДАsoft»

Твердыня модульных языков
Текущее время: 16 окт 2018, 01:48

Часовой пояс: UTC + 2 часа




Начать новую тему Ответить на тему  [ Сообщений: 6 ] 
Автор Сообщение
 Заголовок сообщения: Биндинги к внешним библиотекам
СообщениеДобавлено: 05 апр 2014, 19:52 
Не в сети
Аватара пользователя

Сообщения: 904
Откуда: Днепропетровская обл.
Я считаю текущие возможности по пристыковке к внешним библиотекам, предлагаемые транслятором Ofront, совершенно недостаточными и даже слегка странноватыми. Смотрите как Йозеф предлагает задействовать возможности внешних библиотек (привожу на примере Windows, но с Linux те же пироги):
Код: "OBERON"
  1. MODULE WinApi;
  2. IMPORT SYSTEM;
  3.  
  4. PROCEDURE -Beep* (dwFreq, dwDuration: INTEGER): INTEGER "Beep(dwFreq, dwDuration)";
  5.  
  6. END WinApi.
Сие транслируется в примерно такой Си-файл (WinApi.c):
Код: "C"
/*  Ofront 1.2 -xtspkae */
#include "SYSTEM.h"
 
#define WinApi_Beep(dwFreq, dwDuration) Beep(dwFreq, dwDuration)
И в такой заголовочный файл (WinApi.h):
Код: "C"
/*  Ofront 1.2 -xtspkae */
 
#ifndef WinApi__h
#define WinApi__h
 
#include "SYSTEM.h"
 
import void *WinApi__init(void);
 
#define WinApi_Beep(dwFreq, dwDuration) Beep(dwFreq, dwDuration)
 
#endif
На практике это означает, что при трансляции WinApi.c никакого машинного кода создано не будет, только макрос. Поэтому подразумевается, что нужно сделать ещё и такое:
Код: "OBERON"
  1. MODULE WinApi;
  2. IMPORT SYSTEM;
  3.  
  4. PROCEDURE -includewindows "#include <windows.h>";
  5. PROCEDURE -beep (dwFreq, dwDuration: INTEGER): INTEGER "Beep(dwFreq, dwDuration)";
  6.  
  7. PROCEDURE Beep* (dwFreq, dwDuration: INTEGER): INTEGER;
  8. BEGIN RETURN beep(dwFreq, dwDuration) END Beep;
  9.  
  10. END WinApi.
Что уже даст такой WinApi.c:
Код: "C"
/*  Ofront 1.2 -xtspkae */
#include "SYSTEM.h"
 
export INTEGER WinApi_Beep (INTEGER dwFreq, INTEGER dwDuration);
 
#define WinApi_beep(dwFreq, dwDuration) Beep(dwFreq, dwDuration)
#include <windows.h>
 
INTEGER WinApi_Beep (INTEGER dwFreq, INTEGER dwDuration)
{
return WinApi_beep(dwFreq, dwDuration);
}
Как видим, приходится делать прослойку, враппер. И у такого решения есть несколько недостатков:

  1. Снижение эффективности кода (оверхед) за счёт присутствия вспомогательного слоя (как по памяти, так и по быстродействию)
  2. Дополнительные усилия по двойному переписыванию функций;
  3. Неприятная штука: приходится впускать всю область видимости включаемого файла (например, windows.h) в тело нашего модуля и накладывать её на наш код, это потенциально опасно;
  4. Используется механизм пристыковки с опорой не только на наш сгенерированный Ofront'ом биндинг, но и на существующий подключенный из него *.h-файл. Это двойная работа для компилятора: ведь нужно обработать наш биндинг и тот, включенный из него, который, собственно, и делает всю работу. А ещё возможны накладки в виде несовместимости при описании типов и структур данных (из-за того, что типы Оберона отличаются от типов Си);
  5. Ну и, наконец, результирующий наш бинарник в итоге будет импортировать все функции такого модуля-биндинга, даже если они и не задействованы. Это создаёт дополнительные сложности для смартлинковки (в XDev).


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Биндинги к внешним библиотекам
СообщениеДобавлено: 05 апр 2014, 20:12 
Не в сети
Аватара пользователя

Сообщения: 904
Откуда: Днепропетровская обл.
Серьёзным сдерживающим фактором, который мешает задействовать Ofront для активной разработки под Windows, есть элементарное отсутствие удобных средств для подстыковки к WinApi. Я сделал (для XDev) импорт некоторых функций указанным выше способом, но пришло время признать, что нужно решать эту проблему более кардинально.

В состав BlackBox и POW! входят модули-прослойки к WinApi, но чтобы задействовать их в Ofront'е — придётся пересмотреть принятый в нём способ описания процедур в биндингах (принятый сейчас способ можно оставить, т.к. у него есть свои достоинства).

Я рассмотрел как это реализовано в BlackBox, POW!, ETH Oberon, Delphi. Обычно для описания внешней процедуры кроме Оберон-имени и списка параметров (и типа результата) нужно указать три параметра:

    модель вызова процедуры;
    имя библиотеки, в которой находится процедура;
    имя процедуры (на тот случай если оно отличается от обероновского).

Самым важным конечно является имя библиотеки, остальные параметры в идеале можно опускать, тогда будет принято значение по умолчанию (модель вызова по умолчанию, т.е. __stdcall, и такое же имя, как и описано).

Я пока что в раздумьях насчёт синтаксиса, надо посоветоваться по этому вопросу с Норайром.


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Биндинги к внешним библиотекам
СообщениеДобавлено: 07 апр 2014, 11:50 
Не в сети

Сообщения: 22
Олег!

Во-первых, спасибо за наводки по Ofront'у: для меня это оказалось удобно и полезно.
Цитата:
code procedures should only be exported if the names involved are very unlikely to produce a name clash or if efficiency is of highest priority

Либо прослойка, либо эффективность. Я использую для Linux описания функций в .c0 .h0 вместо include. В примере выше я бы вставил код типа
Код: "C"
 
#include <my_windows.h>
BOOL WINAPI Beep(_In_ DWORD dwFreq, _In_ DWORD dwDuration);
 

В my_windows.h я бы вставил BOOL, WINAPI, DWORD, а не тащил бы всю область видимости windows.h


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Биндинги к внешним библиотекам
СообщениеДобавлено: 07 апр 2014, 17:19 
Не в сети
Аватара пользователя

Сообщения: 904
Откуда: Днепропетровская обл.
Норайр за минимализм и масимальную портабельность. С учётом архитектуры Ofront'а мы выработали следующее решение в духе Оберона: системные процедуры, помеченные "PROCEDURE - ", для которых не задано тело:
Код: "OBERON"
  1. PROCEDURE- CreateWindowExA* (dwExStyle: SET; lpClassName: PtrSTR;
  2. lpWindowName: PtrSTR; dwStyle: SET; X: INTEGER; Y: INTEGER; nWidth: INTEGER;
  3. nHeight: INTEGER; hWndParent: HWND; hMenu: HMENU; hInstance: HINSTANCE;
  4. lpParam: PtrVoid): HWND;
  5.  
  6. PROCEDURE- CreateWindowExW* (dwExStyle: SET; lpClassName: PtrWSTR;
  7. lpWindowName: PtrWSTR; dwStyle: SET; X: INTEGER; Y: INTEGER; nWidth: INTEGER;
  8. nHeight: INTEGER; hWndParent: HWND; hMenu: HMENU; hInstance: HINSTANCE;
  9. lpParam: PtrVoid): HWND;
  10.  
  11. PROCEDURE- CreateWindowEx* (dwExStyle: SET; lpClassName: PtrSTR;
  12. lpWindowName: PtrSTR; dwStyle: SET; X: INTEGER; Y: INTEGER; nWidth: INTEGER;
  13. nHeight: INTEGER; hWndParent: HWND; hMenu: HMENU; hInstance: HINSTANCE;
  14. lpParam: PtrVoid): HWND "CreateWindowExA(dwExStyle, lpClassName, lpWindowName,
  15. dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)";
превращаются доработанным Ofront'ом не в макросы, а в прототипы:
Код: "C"
#define WinApi_CreateWindowEx(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, \
nHeight, hWndParent, hMenu, hInstance, lpParam) CreateWindowExA(dwExStyle, lpClassName, \
lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)

 
#define WinApi_CreateWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, \
nHeight, hWndParent, hMenu, hInstance, lpParam) CreateWindowExA(dwExStyle, lpClassName, \
lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)

 
__EXTERN INTEGER __CALL CreateWindowExA(SET dwExStyle, INTEGER lpClassName,
INTEGER lpWindowName, SET dwStyle, INTEGER X, INTEGER Y, INTEGER nWidth,
INTEGER nHeight, INTEGER hWndParent, INTEGER hMenu, INTEGER hInstance,
INTEGER lpParam);
 
#define WinApi_CreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, \
nHeight, hWndParent, hMenu, hInstance, lpParam) CreateWindowExW(dwExStyle, lpClassName, \
lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)

 
__EXTERN INTEGER __CALL CreateWindowExW(SET dwExStyle, WinApi_PtrWSTR lpClassName,
WinApi_PtrWSTR lpWindowName, SET dwStyle, INTEGER X, INTEGER Y, INTEGER nWidth,
INTEGER nHeight, INTEGER hWndParent, INTEGER hMenu, INTEGER hInstance, INTEGER lpParam);

Атрибуты __EXTERN и __CALL для удобства вынесены в SYSTEM.h и для платформы Windows их определение выглядит так:
Код: "C"
#define __EXTERN __declspec(dllimport)
#define __CALL __stdcall


Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Биндинги к внешним библиотекам
СообщениеДобавлено: 08 апр 2014, 11:01 
Не в сети
Аватара пользователя

Сообщения: 904
Откуда: Днепропетровская обл.
Здравствуйте, Дмитрий! Добро пожаловать на форум.

Почему-то Ofront не очень известен даже среди оберонщиков, но я нахожу его великолепным, в т.ч. и как основу для своих усовершенствований. И я давно хотел приспособить Ofront для разработки на Обероне-2 вместо Си под Windows 32/64 бит, но ничего не имею и против Linux. Поэтому выработанное нами решение призвано быть опорой на платформу (целевая платформа Ofront'а — это язык Си) для использования на этих (и других, вплоть до ARM) архитектурах.

Так что пользуйтесь, критикуйте, предлагайте.

Сейчас активно работаю над адаптацией к Ofront'у (указанным выше способом) биндинга WinApi из BlackBox. Удалось успешно собрать пример MoveWindow из статьи "Как создать программу *.exe". На очереди — адаптация биндинга к 64 битам. Закончу — отпишусь.


Вложения:
Комментарий к файлу: Адаптированный к XDev/WinDev исходник + собранное приложение "MoveWindow" для Windows 32/64bit
MoveWindow.zip [5.78 КБ]
Скачиваний: 167
Вернуться к началу
 Профиль  
Ответить с цитатой  
 Заголовок сообщения: Re: Биндинги к внешним библиотекам
СообщениеДобавлено: 02 дек 2014, 19:57 
Не в сети
Аватара пользователя

Сообщения: 904
Откуда: Днепропетровская обл.
В принципе, биндинги к WinAPI и SDL уже можно использовать и для 32, и для 64 бит. Мне сложно протестировать корректную работу всех функций, использованных типов и записей, поэтому, как водится, используем на свой страх и риск. Наличия проблем не исключаю. Но работает.


Вернуться к началу
 Профиль  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 6 ] 

Часовой пояс: UTC + 2 часа


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

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


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

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group
Тех.поддержка phpBB