Page 1 of 1

C + KolibriOS.lib

Posted: Wed Feb 14, 2018 11:54 pm
by 0CodErr
Здесь есть один нюанс: пришлось объявить фиктивный union в некоторых структурах.
В частности

Code: Select all

struct TSize{
  union{
    struct{
      unsigned short Height;
      unsigned short Width;
    };
    unsigned long Value;
  };
};
А так она объявлена изначально

Code: Select all

  TSize = Packed Record
    Height: Word;
    Width:  Word;
  End;
А дело всё в том, что в отличие от си-шных компиляторов, компилятор Delphi ведёт себя более рационально: если возвращаемое значение умещается в регистре, то оно и возвращается в регистре, причём, даже если это структура.
Си-шные же компиляторы структуры в регистре не возвращают.
Было проверено в компиляторах Borland C++, Open Watcom, GCC, MSVC.
В стандарте я ничего не нашёл по этому поводу.

В KolibriOS.lib не так много функций, возвращающих значения в структурах, вот они:

Code: Select all

Function  GetKey: TKeyboardInput; StdCall; External 'KolibriOS';
Function  GetSystemTime: TSystemTime; StdCall; External 'KolibriOS';
Function  GetScreenMax: TPoint; StdCall; External 'KolibriOS';
Function  GetLastDrawnBackgroundRect: TRect; StdCall; External 'KolibriOS';
Function  GetButton: TButtonInput; StdCall; External 'KolibriOS';
Function  GetSystemDate: TSystemDate; StdCall; External 'KolibriOS';
Function  GetMousePos: TPoint; StdCall; External 'KolibriOS';
Function  GetWindowMousePos: TPoint; StdCall; External 'KolibriOS';
Function  GetMouseScroll: TPoint; StdCall; External 'KolibriOS';
Function  GetBackgroundSize: TSize; StdCall; External 'KolibriOS';
Function  GetScreenWorkingArea: TRect; StdCall; External 'KolibriOS';
Function  GetSkinMargins: TRect; StdCall; External 'KolibriOS';
Function  GetScreenSize: TSize; StdCall; External 'KolibriOS';
Из них только эти возвращают структуры, не помещающиеся в регистре:

Code: Select all

Function  GetScreenWorkingArea: TRect; StdCall; External 'KolibriOS';
Function  GetLastDrawnBackgroundRect: TRect; StdCall; External 'KolibriOS';
Function  GetSkinMargins: TRect; StdCall; External 'KolibriOS';
для них способ с union работать не будет.

Сначала пример для Borland C++

Необходимые инструменты

Code: Select all

BCC32    — компилятор Borland C++
LINK     — линкер от Microsoft
LD       — GNU линкер
OBJCOPY  — утилита для преобразования объектных файлов
Собирается он вот так(make.bat):

Code: Select all

Set NAME=test
BCC32 -c %NAME%.c
LINK -edit %NAME%.obj
LD -T LScript.x %NAME%.obj -o %NAME%.kex -L %KolibriOS% -l KolibriOS
OBJCOPY -O binary -j .all %NAME%.kex
%KolibriOS% — директория, в которой находится KolibriOS.lib, которую можно взять из темы Delphi7 examples http://board.kolibrios.org/viewtopic.php?f=33&t=3469
LScript — линкер-скрипт для GNU-линкера LD

В результате получаем окно с выведенным в него текстом:
C+KolibriOS.lib.png
C+KolibriOS.lib.png (4.17 KiB)
Viewed 7674 times
Downloaded 359 times

Re: C + KolibriOS.lib

Posted: Thu Feb 15, 2018 11:42 am
by Leency
У тебя еще есть доступ к kolibri-n.org?
Буду благодарен если зальешь.

Re: C + KolibriOS.lib

Posted: Fri Feb 16, 2018 6:16 pm
by 0CodErr
Leency, добавить пример можно.
Насчёт описания к нему — не знаю, может нужно что-то уточнить.
Хорошо бы кто-то ещё попробовал. (Например, ты пробовал BigSample http://board.kolibrios.org/viewtopic.php?f=2&t=3587 , и у тебя он собрался и работал.)

Другие компиляторы декорируют stdcall функции.

Например, Open Watcom по умолчанию декорирует stdcall функции, добавляя перед
именем функции знак подчёркивания и суффикс "@size" после имени _FunctionName@size.

Существует флаг компилятора

Code: Select all

zz remove "@size" from __stdcall function names 
но вот флага, убирающего подчёркивание я не нашёл.

Можно решить вопрос добавлением такой прагмы в исходный код

Code: Select all

#pragma aux __stdcall "*" 
В GCC наоборот, есть -fno-leading-underscore(убирает подчёркивание),
но флаг убирающий "@size" -kill-at работают только для dll. C dlltool аналогично.
С MSVC похоже тоже есть такая проблема.

Не хотелось бы изобретать велосипед, нужно всего лишь -kill-at и -fno-leading-underscore но чтобы работало для объектных файлов MSCOFF, а не только для dll.
Я, конечно, поискал немного в сети. Некоторые советуют сделать dll и вызывать функции оттуда, некоторые советуют сделать def-файл(это дополнительная работа, функций может быть 100500).
Но немало тех, кому нужно было прилинковать именно объектник, а dll и def-файл по каким-то причинам не подходят.

Ну в общем, я ещё немного поищу, если не найду, то придётся сделать для этого мини тулзу.
В принципе прогуляться по таблице символов — это не проблема, именно это и происходит в утилите CoffDump http://board.kolibrios.org/viewtopic.php?f=9&t=3577
Думаю, что это могло бы пригодиться даже не только здесь для KolibriOS.

Вот так я собирал с помощью Open Watcom

Code: Select all

Set NAME=test
WCC386 -s %NAME%.c
LINK -edit %NAME%.obj
LD -T LScript.x %NAME%.obj -o %NAME%.kex -L %KolibriOS% -l KolibriOS
OBJCOPY -O binary -j .all %NAME%.kex
ключ -s для компилятора WCC386 означает "remove stack overflow checks".

LScript в данном случае немного другой, так как компилятор WCC386 создаёт секции с другими названиями(CONST, CONST2) и
функция Main имеет в конце знак подчёркивания Main_
Downloaded 358 times

Re: C + KolibriOS.lib

Posted: Fri Feb 16, 2018 6:38 pm
by Leency
BigSample я когда-то пробовал и он у меня собирался.

Re: C + KolibriOS.lib

Posted: Mon Feb 26, 2018 7:05 pm
by 0CodErr
Чтобы собрать пример на Си с помощью GCC/MSVC была создана крохотная утилита KillAt http://board.kolibrios.org/viewtopic.php?f=2&t=3673

Если использовать ключ -fno-leading-underscore для GCC, то
в линкер-скрипте LScript вместо "_Main" следует использовать "Main".
Потом вызвать KillAt без ключей, вот так:

Code: Select all

GCC -fno-leading-underscore -c %NAME%.c -o %NAME%.obj
KillAt %NAME%.obj
Или можно запустить утилиту KillAt с ключом -L

Code: Select all

GCC -c %NAME%.c -o %NAME%.obj
KillAt -L %NAME%.obj
для MSVC должно быть аналогично.