На мой предыдущий вопрос ответа нет (или никто ничего не знает). Зайду к моей проблемке с другой стороны. Нигде не нашел информации об использовании ncurses в паскале. Есть малость для Си. Но это для меня сложно. Есть ли где-то какая-нибудь информация именно для паскаля?
Я престарелый гуманитарий. Изучением Паскаля я занялся, потому что так захотелось. Пытался Си, но не идет. Какой-то он бардачный, сумбурный и корявый. А Паскаль в отличие от Си более стройный, логичный и понятный.
Изучаю самостоятельно, продираясь через откровенную макулатуру и выискивая ценную информацию. Спасают, в основном, форумы. Этот сайт, в частности, очень помогает. Правда информация не редко подается слишком сжато. Хотелось бы некой разжеванности. В интернете полезной информации практически не найти. Поиск выдает совершенно не нужную/неверную информацию (коммерция, что поделаешь). И эта тенденция растет год от года. Жаль.
По теме. О ncurses есть, например, очень не плохой сайт. Но сугубо для Си. Что-то пытался, но ступорится уже на подключении модуля. Сам ncurses установлен.
Надо понимать, что там за кулисами, и 1:1 переписывать. Машинный фундамент у Паскаля и Си общий.
Цитата
Что-то пытался, но ступорится уже на подключении модуля.
А что значит, подключение модуля? В моей практике, если модуля привязок хорошего, как нужно мне, нет, то его нужно писать. А писать все привязки обычно лень, хотя, конечно, автоматические генераторы серьёзно упрощают жизнь. Но написать привязки для пары-тройки функций вообще не проблема.
По ссылке я увидел:
main(int argc,char *argv[]) { // инициализация (должна быть выполнена // перед использованием ncurses) initscr();
// перемещение курсора в стандартном экране y=10 x=30 move(10,30);
NCURSES_EXPORT — судя по названию, это макрос, который навешивает компилятороспецифичные атрибуты, а также они зависят от того, компилируется ли ncurses DLL или какой-то другой код, который от DLL зависит. Внутри этого макроса некий «WINDOW *», то есть, указатель на что-то. В примере на Си, как видно, результат отбрасывается, так что и WINDOW * полноценно можно не переносить. Впрочем, может, и не нужно переносить. Вот в Win32API все структуры достаточно стабильны, и если переписать их с Си на Делфи или Аду, то они сохраняют актуальность, а вот другие програиисты на Си такой дисциплиной не отличаются, и у них и размер, и прочее может без предупреждения меняться.
Короче, пишем:
const Ncurses = 'ncurses.so';
type PCursesWindow = Pointer;
function initscr: PCursesWindow; cdecl; external Ncurses name 'initscr';
Идём дальше.
#define move(y,x) wmove(stdscr,(y),(x))
Макрос. Ясно. Значит, на самом деле нужен wmove. Ищем wmove.
Блин, тяжёлый случай. Я вот вижу этот код первый раз и без понятия, объявлен ли NCURSES_REENTRANT. Лучше бы ему быть объявленным, потому что Паскаль умеет импортировать только процедуры и функции. Переменные и константы умеет экспортировать, но не импортировать. В Win32 API такой фигни нет. Лишний повод понять, до чего же хорошо в Microsoft пишут на Си, кое-кому бы поучиться.
Понадеемся, что объявлен.
Тогда:
function stdscr: PCursesWindow; cdecl; external Ncurses name 'stdscr';
Теперь возвращаемся к макросу:
function move(y, x: Integer): Integer; inline; begin Result := wmove(stdscr, y, x); end;
Какие же козлы. Ну как им объяснить, что нельзя использовать varargs. В хороших языках программирования именно ради безопасности его нет, но вдруг приходится обращаться к библиотеке на Си, и тут же там какой-то козёл написал varargs. Вот в Win32 API такого почти не бывает. Я только одну функцию навскидку знаю. До чего же хорош Microsoft.
В языке Ада их нормально ни вызвать, ни реализовать. В Delphi можно вызвать, но нельзя реализовать. В FPC, наверное, тоже.
Так как в Паскале вызвать можно (синтаксис будет cdecl; varargs;), я подумал, может, так и сделать. Но потом решил сделать как надо. А будет лучше заменить printw на addstr, а форматирование, если хочется, через SysUtils.Format всегда доступно.
NCURSES_EXPORT(int) waddnstr(WINDOW *win, const char *astr, int n)
Вот это уже можно переписать на Паскаль:
function waddnstr(win: PCursesWindow; const astr: PAnsiChar; n: Integer): Integer; cdecl; external Ncurses name 'waddnstr';
Теперь макрос:
function addstr(const str: PAnsiChar): Integer; inline; begin Result := waddnstr(stdscr, str, -1); end;
Попутно я понял, зачем тут n и -1. Это же длина в байтах. Но это небезопасно, и мы же не хотим, чтоб процессор лишний раз бегал по строке, ведь у нас полноценный язык программирования, способный на такой подвиг, как запомнить длину строки. Значит, лучше будет
#define addnstr(str,n) waddnstr(stdscr,(str),(n))
function addnstr(const str: PAnsiChar; n: Integer): Integer; inline; begin Result := waddnstr(stdscr, str, n); end;