OberonCore
https://forum.oberoncore.ru/

Замена условным директивам ifdef
https://forum.oberoncore.ru/viewtopic.php?f=29&t=2062
Страница 1 из 3

Автор:  Роман М. [ Понедельник, 16 Ноябрь, 2009 23:53 ]
Заголовок сообщения:  Замена условным директивам ifdef

Как заменяются "традиционные" директивы IFDEF, ELSE, ENDIF при написании межплатформенного кода?

К примеру, существует код на Free Pascal:
Код:
function  FPS_ISDIR(iAttr:Cardinal) : Boolean;
{$IFDEF WIN32}
begin
Result := Boolean(iAttr and faDirectory);
end;
{$ELSE}
begin
Result := BaseUnix.FPS_ISDIR(iAttr);
end;
{$ENDIF}

Автор:  Илья Ермаков [ Вторник, 17 Ноябрь, 2009 00:01 ]
Заголовок сообщения:  Re: Замена условным директивам ifdef

Есть некая служба (например, файлы).

Делается модуль (например, Files), в котором нет платформенно-зависимого кода. А объявлены абстрактные типы-интерфейсы. Конкретные их реализации засунуты в другой модуль, про который никто не знает (HostFiles, или там LinHostFiles, и т.п.). Важно понять, что не Files импортирует HostFiles, а наоборот: HostFiles импортирует Files. HostFiles реализует все абстракные типы ("классы" в привычных дельфистам терминах) и втыкает специальный объект-разъём, директорию: Files.dir. Через этот объект все обращения динамически перенаправляются модулю реализации. Таким образом, реализация подключается динамически, и даже может динамически без перезапуска программы меняться.

Почитайте учебник ББ раздел 3 "Приёмы проектирования".

Автор:  Евгений Темиргалеев [ Вторник, 17 Ноябрь, 2009 00:04 ]
Заголовок сообщения:  Re: Замена условным директивам ifdef

Роман М. писал(а):
Как заменяются "традиционные" директивы IFDEF, ELSE, ENDIF при написании межплатформенного кода?
Они заменяются более современным архитектурным подходом. Конкретный пример - см. пост Ильи.

Автор:  Роман М. [ Вторник, 17 Ноябрь, 2009 00:07 ]
Заголовок сообщения:  Re: Замена условным директивам ifdef

Таким образом, банальный перевод из другого языка невозможен без переделки архитектуры?
Ню и ню. :?

Автор:  Евгений Темиргалеев [ Вторник, 17 Ноябрь, 2009 00:10 ]
Заголовок сообщения:  Re: Замена условным директивам ifdef

Можно, конечно, не изучать современных подходов, а воспользоваться (имхо) интерфейсом будущего - составными (+активными) документами http://oberoncore.ru/wiki/blackbox/devselectors

Автор:  bohdant [ Вторник, 17 Ноябрь, 2009 00:14 ]
Заголовок сообщения:  Re: Замена условным директивам ifdef

Цитата:
Как заменяются "традиционные" директивы IFDEF, ELSE, ENDIF при написании межплатформенного кода?

Эту гадость я просто ненавижу :evil: . О какой читабельности может быть речь если невозможно понять о чем где идет речь.

Я не знаю как сделано в ЧЯ, расскажу как сделано в ГБ.
Системные функции (или лучше сказать платформ-зависимые) выносятся в отдельные модули (ядро) типа:
Unix.Platform.Mod, Win32.Platform.Mod и т.п.
В зависимости от целевой платформы компилируется нужный модуль(компонентная система однако), и это происходит незаметно со стороны пользовательской программы(модуля), т.к. мы вызываем Platform.FPS_ISDIR - результат булеан, и никакой путанины.
Кстати почти аналогично можно писать на FPC, но видать IFDEF писать проще :cry:

Автор:  Valery Solovey [ Вторник, 17 Ноябрь, 2009 00:16 ]
Заголовок сообщения:  Re: Замена условным директивам ifdef

Цитата:
Они заменяются более современным архитектурным подходом.

А смысл этого подхода - не держать в одном файле код для разных архитектур.
Вот некоторые из причин:
1. сложность чтения (эти все if-ы туманят мозг).
2. сложность поддержки.

Автор:  Valery Solovey [ Вторник, 17 Ноябрь, 2009 00:18 ]
Заголовок сообщения:  Re: Замена условным директивам ifdef

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

Автор:  Евгений Темиргалеев [ Вторник, 17 Ноябрь, 2009 00:23 ]
Заголовок сообщения:  Re: Замена условным директивам ifdef

bohdant писал(а):
Кстати почти аналогично можно писать на FPC, но видать IFDEF писать проще :cry:
Проще, пожалуй, если забить на архитектуру и горизонт планирования выставить по +5 минут процесса написания.

Автор:  bohdant [ Вторник, 17 Ноябрь, 2009 00:25 ]
Заголовок сообщения:  Re: Замена условным директивам ifdef

Valery Solovey писал(а):
Цитата:
Они заменяются более современным архитектурным подходом.

А смысл этого подхода - не держать в одном файле код для разных архитектур.
Вот некоторые из причин:
1. сложность чтения (эти все if-ы туманят мозг).
2. сложность поддержки.

100%
небольшой (реально небольшой, там черт ногу сломит) из уважаемой мной библиотечки Кладова KOL:
Код:
//[OPTIONS]
{$ifdef cpu86}
{$A-} // align off, otherwise code is not good
{$endif cpu86}
{+}

{$Q-} // no overflow check: this option makes code wrong
{$R-} // no range checking: this option makes code wrong
{$T-} // not typed @-operator
//{$D+}
//______________________________________________________________________________
//
//{$DEFINE INPACKAGE} // Uncomment this line while rebuild MCK package
// for Delphi3 only, then restore the comment mark!!!!!!!!!!!!!!!!!!!!
//______________________________________________________________________________

{$IFDEF INPACKAGE} // use this symbol in packages requiring kol.pas
  {$WARNINGS OFF}
  {$DEFINE NOT_USE_AUTOFREE4CONTROLS}
  {$DEFINE PAS_VERSION}
  {$UNDEF ASM_VERSION}
  {$UNDEF ASM_UNICODE}
{$ENDIF}
{$IFDEF _D7orHigher}
  {$WARN UNSAFE_TYPE OFF} // Too many such warnings in Delphi7
  {$WARN UNSAFE_CODE OFF}
  {$WARN UNSAFE_CAST OFF}
{$ENDIF}

//[START OF INTERFACE]
interface

{$IFDEF NEW_ALIGN}
  {$UNDEF OLD_ALIGN}
{$ELSE}
  {$IFNDEF OLD_ALIGN}
    {$DEFINE NEW_ALIGN}
  {$ENDIF}
{$ENDIF}

{$IFDEF OLD_ALIGN}
  {$UNDEF NEW_ALIGN}
{$ELSE}
  {$IFNDEF NEW_ALIGN}
    {$DEFINE NEW_ALIGN}
  {$ENDIF}
{$ENDIF}

{$IFNDEF OLD_TRANSPARENT}
  {$DEFINE NEW_TRANSPARENT}
{$ENDIF}

{$IFNDEF NOT_USE_AUTOFREE4CONTROLS}
  {$DEFINE USE_AUTOFREE4CONTROLS}
  {$DEFINE USE_AUTOFREE4CHILDREN}
{$ENDIF}

{$IFDEF SMALLEST_CODE}
  {$DEFINE NOT_UNLOAD_RICHEDITLIB}
  {$DEFINE SMALLER_CODE}
{$ENDIF}

{$IFDEF NOT_USE_RICHEDIT}
  {$DEFINE NOT_UNLOAD_RICHEDITLIB}
{$ENDIF}

//{$DEFINE DEBUG_GDIOBJECTS}
//{$DEFINE CHK_GDI}

//[USES]
uses {$IFDEF WIN}messages, windows {$IFNDEF NOT_USE_RICHEDIT}, RichEdit {$ENDIF}{$ENDIF WIN}
     {$IFDEF LIN}Libc, Xlib{$ENDIF}
     {$IFDEF GTK}, Glib2 , Gdk2, Gtk2, pango {$ENDIF GTK}
     {$IFDEF CHK_GDI}, ChkGdi {$ENDIF};
//[END OF USES]

{$IFDEF LIN}
  {$DEFINE global_declare} {$I KOL_Linux.inc} {$UNDEF global_declare}
////type HDC = TGC; // from Xlib (temporary definition?)
{$ENDIF LIN}

{$ifdef wince}
  {$R KOL-CE.rc}
{$endif wince}

var
  AppTheming: boolean;
{$IFDEF DEBUG_GDIOBJECTS}
var
  BrushCount: Integer;
  FontCount: Integer;
  PenCount: Integer;
{$ENDIF}

{$IFDEF UNICODE_CTRLS}
  {$IFDEF _D2}
    {$ERROR 'Delphi 2 cannot compile with UNICODE_CTRLS defined!'}
  {$ENDIF}
const
   SizeOfKOLChar = SizeOf(WideChar);
{$ifdef wince}
        I_SKIP = -2;
{$endif wince}

 type
    KOLString = WideString;
         KOL_String = type WideString;
    KOLChar = type WideChar;
    PKOLChar = PWideChar;
         PKOL_Char = type PWideChar;
{$ELSE}
const
   SizeOfKOLChar = SizeOf(AnsiChar);

 type
    KOLString = String;
         KOL_String = type String;
    KOLChar = type AnsiChar;
    PKOLChar = PAnsiChar;
         PKOL_Char = type PAnsiChar;
   {$IFDEF ASM_VERSION}
     {$DEFINE ASM_UNICODE}
     {$UNDEF PAS_VERSION}
   {$ENDIF}
{$ENDIF}

{$IFNDEF ASM_VERSION}
  {$DEFINE PAS_VERSION}
{$ENDIF ASM_VERSION}

{BCB++}(*type DWORD = Windows.DWORD;*){--BCB}

{$IFDEF WIN}
//{_#IF [DELPHI]}
{$IFDEF WIN32}
  {$INCLUDE delphicommctrl.inc}
  {$IFDEF UNICODE_CTRLS}
    {$DEFINE interface_part} {$I KOL_unicode.inc} {$UNDEF interface_part}
  {$ENDIF UNICODE_CTRLS}
{$ENDIF WIN32}
//{_#ENDIF}
{$ENDIF WIN}


Автор:  Евгений Темиргалеев [ Вторник, 17 Ноябрь, 2009 00:27 ]
Заголовок сообщения:  Re: Замена условным директивам ifdef

bohdant писал(а):
небольшой (реально небольшой, там черт ногу сломит)...
Пока сам пишешь и потихоньку наворачиваешь условную компиляцию - все понятно. :)

Автор:  bohdant [ Вторник, 17 Ноябрь, 2009 00:29 ]
Заголовок сообщения:  Re: Замена условным директивам ifdef

Евгений Темиргалеев писал(а):
bohdant писал(а):
Кстати почти аналогично можно писать на FPC, но видать IFDEF писать проще :cry:
Проще, пожалуй, если забить на архитектуру и горизонт планирования выставить по +5 минут процесса написания.

Так там и "так" и "так" делают. Беда в том, что IFDEF проще применять, когда не продумана архитектура. Но вылевается это потом сами знаете, что не в 5 минут (особенно перед новым годом :) )

Автор:  Роман М. [ Вторник, 17 Ноябрь, 2009 00:30 ]
Заголовок сообщения:  Re: Замена условным директивам ifdef

Нет, я не про локализацию, а про другие языки программирования. Спасибо всё равно.

Евгений Темиргалеев писал(а):
Можно, конечно, не изучать современных подходов, а воспользоваться (имхо) интерфейсом будущего активными (составными) документами http://oberoncore.ru/wiki/blackbox/devselectors

Таким образом, мы жёстко привязываем код к BlackBox, что не совсем правильно. Хотя, выбора среди компиляторов КП итак практически нет...

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

Автор:  Иван Кузьмицкий [ Вторник, 17 Ноябрь, 2009 00:53 ]
Заголовок сообщения:  Re: Замена условным директивам ifdef

BlackBox - это не только компилятор, а ещё и среда выполнения, мини-ОС.

Автор:  Valery Solovey [ Вторник, 17 Ноябрь, 2009 01:26 ]
Заголовок сообщения:  Re: Замена условным директивам ifdef

Роман М. писал(а):
Нет, я не про локализацию, а про другие языки программирования.
Вы говорили про банальный перевод на другие языки. Такое возможно только между диалектами. В общем случае это далеко не банально. Взять, хотя бы, в качестве целевого языка LISP.

В Обероне был сделан упор на то, чтобы при программировании не отвлекалось внимание на посторонние вещи. В программе (и в Вашей в том числе) первостепенное значение имеет алгорим, и пока он не работает, платформа значения не имеет. Каким образом в Обероне пытаются избавиться от распыления внимания? Вот некоторые механизмы:
1. сильно разнесённые вещи располагают в разных модулях. Для правильного использования этого механизма уже требуется хорошая дисциплина у программиста. В противном случае, эффект может быть даже отрицательным.
2. уменьшение числа конструкций с синонимичной семантикой. Оставляются только те конструкции, которые настолько мощные, чтобы решать задачи вместо исключённых конструкций. Здесь дисциплина значения уже не имеет: программисту не оставляют шанса выбрать неправильно. Вот на этом этапе, по-видимому, директивы и ушли (они почти без потери производительности реализуются другими средствами). Вот здесь и появляется сложность при портировании. (в сторону) Хотя, у Вирта директив вроде и не было никогда. Эти рычажочки придумала другая голова, не светлая, а засиженая тараканами.
3. Сильная типизация. Впрочем, у fp она почти такая же.
4. ещё кое-что, что в данном случае будет оффтопом.

Подытоживая, можно сказать, что лёгкий переход вряд ли представляется возможным.

С другой стороны, у Вас же была причина обратиться к Оберонам? Не думаю, что человек, пишущий кроссплатформенные приложения верит в сказку о том, как новый язык программирования решит за него всю задачу. Также маловероятно, что Вы просто хотите кого-нибудь занять делом. Значит, Вас привлекло что-то, что для вас полезно. Основные плюсы Оберона в том, что они, незначительные в начале, со временем жизни проекта растут и преобретают довольно значительные размеры. Я не знаю Вашего проекта и не знаю, планируют ли у Вас кормиться на нём долгое время, поэтому посоветовать менять архитектуру тоже не могу.

Но зато есть другая идея. Нет необходимости менять сразу и архитектуру, и язык. Если есть важная причина перейти на Оберон, то Вы к нему присмотритесь, найдите такие места в своём коде, перенести которые - не тривиальная задача, не спеша и безболезненно для проекта смените их форму на более удобную для портирования. Это может тянуться месяцами без вреда для нервов. А потом уже можно будет сменить и язык.

Автор:  Rifat [ Вторник, 17 Ноябрь, 2009 09:19 ]
Заголовок сообщения:  Re: Замена условным директивам ifdef

Я считаю, что хоть в каком-нибудь виде, но препроцессор необходим. Например, в заголовочных файлах Windows при определении различных констант и т.д часто определение зависит от версии Windows для которой компилируется программа, от того 32 битная или 64 битная программа, UNICODE или нет.
Вот кусок кода из WinUser.h
Код:
#if (_WIN32_WINNT >= 0x0500)
#define WM_MOUSELAST                    0x020D
#elif (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
#define WM_MOUSELAST                    0x020A
#else
#define WM_MOUSELAST                    0x0209
#endif /* (_WIN32_WINNT >= 0x0500) */

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

Автор:  Валерий Лаптев [ Вторник, 17 Ноябрь, 2009 10:48 ]
Заголовок сообщения:  Re: Замена условным директивам ifdef

Вы забываете:
1. программы в ББ - это НЕ ТЕКСТОВЫЕ ФАЙЛЫ
2. Переносится не программа, созданная в ББ, а сам ББ.
3. Или непосредственно исполняемый модуль создается под требуемую среду.
Таким образом, вносить лишнее усложнение в язык-компилятор нет смысла...

Автор:  Роман М. [ Вторник, 17 Ноябрь, 2009 12:11 ]
Заголовок сообщения:  Re: Замена условным директивам ifdef

Общий путь решения понял. Из ваших ответов я пришёл к выводу, что в Оберон портировать затруднительно по той причине, что, скорее всего, придётся изменять архитектуру проекта/программы, что является ёмкой работой и нужно хорошо взвесить, прежде чем решаться на портирование.

Несмотря на это, давайте рассмотрим модуль moduleloader.pas для межплатформенной динамической загрузки библиотек (часть JEDI project). На его примере хотелось бы прийти к его варианту в КП: http://www.koders.com/delphi/fid2CE0842051A76D9F1CD3FAD65EB8D655F47F66EC.aspx?s=parser. Он хорош как пример.

Как я понял, такой модуль стоит разделять на 3 модуля:
  • PlatformUnixModuleloader - реализация UNIX-части
  • PlatformWinModuleloader - реализация Windows-части
  • HostModuleloader - связующий модуль. Что он должен содержать? Я что-то не въезжаю.

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

Автор:  Valery Solovey [ Вторник, 17 Ноябрь, 2009 12:21 ]
Заголовок сообщения:  Re: Замена условным директивам ifdef

Rifat писал(а):
Все эти комбинации по разным модулям разнести практически невозможно, так получится "комбинаторный взрыв".
Комбинаторного взрыва не получится. По крайней мере, пока не произойдёт комбинаторного взрыва виндов. Для каждой версии системы достаточно иметь свои константы, вот и всё.

Автор:  Axcel [ Вторник, 17 Ноябрь, 2009 12:28 ]
Заголовок сообщения:  Re: Замена условным директивам ifdef

Rifat писал(а):
Я считаю, что хоть в каком-нибудь виде, но препроцессор необходим. Например, в заголовочных файлах Windows при определении различных констант и т.д часто определение зависит от версии Windows для которой компилируется программа, от того 32 битная или 64 битная программа, UNICODE или нет.

А я считаю, что с помощью Рефал-0 Ильи Ермакова организовать препроцессинг нефиг делать.

Страница 1 из 3 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/