С+Clarion

В продолжение обсуждения передачи группы в C-функции  как константы а не по ссылке.  Как удалось выяснить, такие группы действительно  копируются на стек по полям и делает это вызывающая программа.  Так что, увы, нет нормального способа использовать такие  функции из Клариона! Если нет возможности «развернуть»  такие группы по полям, то единственный выход — использовать  переходник.

Кстати! Оказывается есть возможность работы с C-функциями,  которые возвращают в качестве результата структуру.
Типа:

my_struct MyFunc();

Данная функция возвращает структуру my_struct.  На самом деле компилятор С генерит вызов такой функции как Clarion-аналог:

MyFunc(*MY_STRUCT _Struct),LONG,RAW,C,NAME('_MyFunc')

Т.е. в качестве первого (скрытого) параметра такая функция  получает указатель на принимающую структуру и одновременно  такая функция возвращает еще и указатель на эту структуру.

Вот такие дела.
Правда непонятно — все-ли C-компиляторы генерят подобный код?
Или это — типа «визитной карточки» отдельных компилятор?

NT>А если разворачивать, то в каком порядке должны идти поля и байты в строках?
NT>WBR, Nick Tsigouro Mailto:N.Tsigouro@mtu-net.ru

Структура «запихивается» на стек как байтовый массив.  Но, так как стековые команды работают не с байтами а со  словами, то и забрасывается группа по словам а не по полям.  Если тип полей группы имеет одинаковый размер со словом  в текущем режиме адресации (16/32 бита), то можно сказать, что  на стек группа забрасывается по полям, начиная с последнего.  Т.е. в результате на вершине стека окажеться первое поле группы.

Например:

typedef struct my_group {
  int field1,field2;
} my_group;
int my_func(my_group);

На Кларионе, интерфейс для вызова функции my_func будет выглядеть так:

MAP
  MODULE('C_LIB')
    my_func(LONG _Field1,LONG _Field2),LONG,C,NAME('_my_func')
  END
END
My_Group GROUP
Field1 LONG
Field2 LONG
END
...
Sum# = my_func(My_Group.Field1,My_Group.Field2)
...

Согласно декларации и аттрибуту «C», перед вызовом функции my_func,  Кларион «забросит» на стек сначала Field2 а потом и Field1.  В результате, на вершине стека будет Field1 а за ним Field2.  Именно такую последовательность и ожидает получить на стеке функция my_func.

Проблемы начинаются, когда поля группы разного типа и/или размер  этих типов не равен размеру слова. На стеке все эти данные  выстраиваются так, как и стояли в группе. Но проблема в том, как  все это выполнить на Кларионе.

Скажем, если предыдущая группа будет такой:

typedef struct my_group
{
  short int field1,field2;
} my_group;

При таком раскладе C-компилятор «загоняет» всю структуру на стек  одной командой PUSH (для 32-битного режима).  А функция уже «снимает» со стека по полям.  На Кларионе не достаточно задекларировать эту функцию так:

MAP
  MODULE('C_LIB')
    my_func(SHORT _Field1,SHORT _Field2),LONG,C,NAME('_my_func')
  END
END

В этом случае компилятор Клариона «забросит» на стек эти параметры как два слова. А функция ожидает эти параметры размещенными в одном слове. В данном случае можно решить эту проблему так:

MAP
  MODULE('C_LIB')
    my_func(LONG _Param),LONG,C,NAME('_my_func')
  END
END
LOC:Param LONG
LOC:ParamGrp GROUP,OVER(LOC:Param)
  Field1 SHORT
  Field2 SHORT
END
...
LOC:ParamGrp.Field1 = 100
LOC:ParamGrp.Field1 = 200
A# = my_func(LOC:Param)
...

Ну а для более сложных структур, естественно, прийдется  хорошенько «поламать» голову!  Хотя, в общем виде, достаточно наложить на нужную стрктуру  группу из LONG-полей (для 32-битного режима) такого размера, что-бы  она перекрывала группу данных и использовать поля этой группы  как параметры для вызова «сложной» C-функции.  Честно говоря, я не знаю как C-компилятор поступает со структурами,  содержащими байтовые поля и строки. Возможно, что так-же как и  описано выше. Вообщем — пробовать надо.

Вообще-то, что-то мне не нравятся такие библиотеки, которые  используют для вызовов PUBLIC-функций механизмы передачи  параметров, не предназначенные для внешнего использования.  Я что-то еще не встречал в библиотеках, предназначеных  для внешнего использования, функции со структурами-параметрами,  которые передавались-бы не по ссылке (адресу) а как константы.  Хотя, возможно, я не прав.