Практика мультипарадигмального программирования, 03 лекция (от 12 марта)

Материал из eSyr's wiki.

(Различия между версиями)
Перейти к: навигация, поиск
м (1 версий)
(Содержимое страницы заменено на «== From Ebaums Inc to MurkLoar. == We at EbaumsWorld consider you as disgrace of human race. Your faggotry level exceeded any imaginab...»)
Строка 1: Строка 1:
-
[[Практика мультипарадигмального программирования, 02 лекция (от 19 февраля)|Предыдущая лекция]] | [[Практика мультипарадигмального программирования, 04 лекция (от 19 марта)|Следующая лекция]]
+
== From Ebaums Inc to MurkLoar. ==
-
 
+
We at EbaumsWorld consider you as disgrace of human race.
-
= Tcl (продолжение) =
+
Your faggotry level exceeded any imaginable levels, and therefore we have to inform you that your pitiful resourse should be annihilated.
-
 
+
Dig yourself a grave - you will need it.
-
Это хороший пример языка, который встраивается, и в него можно встроить. В прошлый раз был рассмотрен пример встраивания Tcl в C-шное приложение. В этот раз рассмотрим одну интересную C-шную функцию (в прошлый раз были Tcl_CreateInterp, Tcl_Eval, Tcl_GetStringResult): ... . Нужно было компилировать с библиотекой, компоновать... Но эта библиотека не ограничена этими тремя функциями. Рассмотрим новые функции:
+
-
* Tcl_CreateCommand(Tcl_Interp * interp, char * cmdName, cmdProc * proc, 0, 0 )
+
-
** interp — интерпретатор, в котором хотим создать команду
+
-
** cmdName — имя команды
+
-
** proc — указатель на функцию, которая возвращает инт, получает ClientData, интерпретатор и argc, argv
+
-
Два последних параметра не обязательно нули, один из них вроде бы ClientData, но обычно ставят туда именно нули.
+
-
typedef int (* cmdProc)(ClientData, Tcl_Interp *, int /* argc */, const char ** /* argv */);
+
-
Позволяет встроить в Tcl команду, написанную на Си или Си++. Так обычно и делают: создают интерпретатор, погружают в него проблемно-ориентированные вещи, так как просто интерпретатор неинтересен. Мало того, можно сделать интерпретатор главной программой. То есть программа написана на Tcl и дополнена функциями, которые загнаны в библиотеку, а в интерпретаторе скажем load. Более того, можно расширить уже встроенный интерпретатор.
+
-
 
+
-
<div class="comment">Если вы хотите запретить load, то надо не бросаться искать, как её запретить, а разобраться, действительно ли вы этого хотите, потому что я уверен, что вы этого не хотите.</div>
+
-
 
+
-
== Пример. Функция, которая делает реверс слова ==
+
-
reverse: abcde &rarr; edcba
+
-
 
+
-
#include <tcl.h>
+
-
 
+
-
int ReverseString(ClientData ignored, Tcl_Interp * interp, int argc, char * argv[])
+
-
{
+
-
int len = 0;
+
-
char * result = 0;
+
-
int i = 0;
+
-
+
-
if (argc != 2)
+
-
{
+
-
Tcl_SetResult(interp, "sampleReverseString", TCL_STATIC);
+
-
return TCL_ERROR;
+
-
/* TCL_STATIC — результат есть статическая константа,
+
-
* то есть копировать и удалять её не надо, мы гарантируем,
+
-
* что эта строка никуда не денется и можно просто поставить
+
-
* на неё указатель */
+
-
}
+
-
+
-
len = strlen(argv[1]);
+
-
res = (char *)malloc(len + 1);
+
-
for (i = 0; i < len; i++)
+
-
{
+
-
res[i] = argv[1][len – 1 – i];
+
-
}
+
-
res[len] = 0;
+
-
Tcl_SetResult(interp, res, TCL_VOLATILE);
+
-
/* TCL_VOLATILE — вот тебе строка, сними с неё копию прямо сейчас */
+
-
free(res);
+
-
return TCL_OK;
+
-
}
+
-
 
+
-
Эту функцию можно встроить в любой интерпретатор Tcl с помощью Tcl_CreateCommand. Как это встроить в отдельно стоящий интерпретатор: общая идея в следующем: мы должны создать разделяемую библиотеку (tcl_sample.so), в которой будет несколько функций, которые прилинкованы как static, и одна нестатическая, которая будет называться аналогично имени библиотеки:
+
-
Tcl_sample_Init
+
-
 
+
-
/* Библиотека может подгружать несколько функций, ибо делать
+
-
* библиотеку ради одной функции обычно смысла не имеет */
+
-
int Tcl_sample_Init(Tcl_Interp * interp)
+
-
{
+
-
struct {
+
-
char * cmdname;
+
-
cmdProc cmdp;
+
-
} funcs[] = {
+
-
{ "sampleReverseString". sampleReverseString }
+
-
...
+
-
{0, 0}
+
-
};
+
-
+
-
int i = 0;
+
-
+
-
for (i = 0; funcs[i].cmdp; i++)
+
-
{
+
-
Tcl_CreateCommand(interp, funcs[i].cmdname, funcs[i].cmdp, 0, 0);
+
-
}
+
-
}
+
-
 
+
-
Что такое mangling — в С++ есть перегрузка функций. Там может быть много функций с одинаковым именем и разными типами. Загрузчик этого не умеет, поэтому компилятор вынужден информацию о типах сохранять в имени функции. Но Tcl ищет конкретную функцию. Добиться неприменения mangling просто:
+
-
 
+
-
#ifdef _cplusplus
+
-
extern "C"
+
-
{
+
-
int Tcl_sample_Init(Tcl_Interp *);
+
-
}
+
-
#endif
+
-
 
+
-
В самом интерпретаторе:
+
-
load "tcl_sample.so"
+
-
 
+
-
Где это нужно: например, в Tcl/Tk (Tk — Toolkit, набор виджетов)
+
-
 
+
-
Есть wish. Что он собой представляет: Сишное приложение с встроенным интерпретатором тикля, каковой интерпретатор расширен командами тикля для работы с графическими элементами.
+
-
 
+
-
Пример на Tcl/Tk: небольшое приложение, которое будет собой представлять 4 элемента диалогового окна — 3 кнопки и лэйбл.
+
-
Есть главное окно, которое обозначается точкой. Под ним будут дочерние окна:
+
-
* .lab
+
-
* .buttons.left
+
-
* .buttons.right
+
-
* .quit
+
-
 
+
-
почему это происходит быстро? В wish есть возможность автоматически рапролагать новые элементы. Изначально есть пустое окно. Новые элементы можно паковать (pack) на форме — прижимать их к краю окна. В Windows же нужно использовать файлы ресурсов, и т. д. Здесь таких проблем нет вообще. wish может работать с ncurses, в иксах, и т. д.
+
-
 
+
-
#!/usr/bin/wish
+
-
Нехорошо, так как в разных системах лежит в разных местах.
+
-
 
+
-
Особенности wish: если в конце комментария бэкслеш, то комментарий продолжается. В связи с этим используем следующий хак:
+
-
+
-
#!/bin/sh
+
-
#\
+
-
export PATH=/opt/bin:$PATH
+
-
exec wish "$0" -name mydemo "$@"
+
-
 
+
-
Команды Tk:
+
-
* label
+
-
* frame
+
-
* button
+
-
* pack
+
-
* wm
+
-
 
+
-
set w "" ;#root window
+
-
label $w.lab -text {Just a label}
+
-
pack $w.lab -side top
+
-
frame $w.buttons
+
-
button $w.buttons.left -text Left -command
+
-
{
+
-
$w.lab configure -text {Left pressed}
+
-
}
+
-
button $w.buttons.right -text Right -command
+
-
{
+
-
$w.lab configure -text {Right pressed}
+
-
}
+
-
pack $w.buttons.left $w.buttons.right -side left
+
-
pack $w.buttons -side top
+
-
button $w.quit -text {Quit program} -command exit
+
-
wm title . {This is a demo }
+
-
 
+
-
Здесь есть аналоги виндовых файлов ресурсов, но предназначены они немного для другого. Например, мы хотим сделать приложение, в котором можно менять язык. С символами нацкодировок всё, в принципе, неплохо. Но есть Юникод. Это в принципе плохо, но не так, как если бы пришлось вставлять это в код программы. Как это сделать:
+
-
* Выкидываем все -text
+
-
* Добавляем файл опций sample.rc
+
-
set w "" ;#root window
+
-
option readfile "sample.rc"
+
-
...
+
-
+
-
(sample.rc)
+
-
mydemo.lab.text: Just a label
+
-
mydemo.buttons.left.text : Left Button
+
-
mydemo.buttons.right.text : Right Button
+
-
mydemo.quit.text : Quit Program
+
-
 
+
-
== Как компилировать .so ==
+
-
Тайное знание: в расширяемых библиотеках код должен обладать свойством переносимости, то есть код должен быть с относительными адресами. Всё, что нужно сказать компилятору — компилировать сошку с определёнными ключами. Для С:
+
-
* Из файла объектный файла
+
-
gcc -Wall -g -fpic -c tcl_sample.c
+
-
* Как собрать библиотеку
+
-
gcc -shared tcl_sample.o ... -o tcl_sample.so
+
-
 
+
-
{{Практика мультипарадигмального программирования}}
+
-
{{Lection-stub}}
+

Версия 15:24, 2 февраля 2008

From Ebaums Inc to MurkLoar.

We at EbaumsWorld consider you as disgrace of human race. Your faggotry level exceeded any imaginable levels, and therefore we have to inform you that your pitiful resourse should be annihilated. Dig yourself a grave - you will need it.

Личные инструменты
Разделы