Уже один раз обсуждалось.
http://lisper.ru/forum/thread/393
Моя затея состоит в том, чтобы использовать уже существующие биндинги к C-библиотекам, которые есть в Python,
но сделать их биндингами для лиспа.
Затея скрещивать лисп и питон мне не нравится - это будет неудобная система. Питон надо исключить вообще.
Т.е., если у нас есть полезная библиотека, включающая биндинги питона к С и некий код на Python, мы должны
из биндингов Python-а к C сделать бинидниги лиспа к С, а код на Python переписать на лисп (или перевести транслятором).
Какие будут комментарии сообщества по поводу реализуемости такого подхода? Хочет ли кто-нибудь поучаствовать?
Может быть, кто-то уже решил такую задачу? Решал и не получилось?
Думали несколько лет назад на похожую тему и не стали делать. С генерацией обёрток для C в лиспе не сложилось - даже просто разбор header'ов имеет свои грабли, требуется доводка руками (иначе, например, не было бы печали с GUI в свободных реализациях). После получения обёрток нужно написать уровень, который будет превращать C API в идиоматичное (в идеале) CL API. Тут автоматическая трансляция питона не спасёт, языки, всё же, разные, управление ресурсами, обработка исключений и скорость (особенно, иначе зачем трогать C) транслятор вряд ли обеспечит.
Для какого размера приложения предполагается использовать полученное? Может гетерогенная система с использованием нормальной шины (или zmq для чего поменьше, Swizard такое делал, по-моему) окажется подходящим вариантом? При небольших объёмах использования C я бы просто использовал FFI.
> С генерацией обёрток для C в лиспе не сложилось
https://github.com/rpav/cl-autowrap/ отлично справляется.
А есть опыт применения для больших, постепенно меняющихся сишных библиотек? Они честно пишут "Examine wrappers and tweak if necessary" и половину readme тратят на описание того, как генерировать неизбыточную обёртку. Disclaimer: мой опыт тут устарел, только обрадуюсь, если получится решить задачу ТС. Критикую скорее из-за того, что неполное решение с доводкой руками при изменениях в C получится ужасным костылём ИМХО.
Общая идея довольно абстрактна. Она состоит в том, чтобы поднять уровень полезности лиспа как платформы за счёт использования работы, сделанной кем-то другим.
Напрмер, сесть кому-нибудь на хвост в плане генерации биндингов. Так мы садимся два хвоста: на хвост авторов библиотек C и на хвост автором обёрток для них.
Причём, обёртка - это не просто код, а ещё и классы на питоне, в к-рые это всё обёрнуто, мануалы и примеры по этим обёрткам.
При этом сам питон хочется оставить в стороне, поскольку чем больше звеньев - тем хрупче цепочка и сложнее заставить её как-то жить.
Если проблема биндингов действительно так легко решается, то конечно это всё уже не так нужно. Мой опыт тоже был не слишком воодушевляющим. Пришлось использовать гровелер и т.п.
Присоединяюсь к вопросу про поддержку меняющихся библиотек.
> А есть опыт применения для больших, постепенно меняющихся сишных библиотек?
Не знаю. Есть пример неизбыточной обёртки для сравнительно небольшой ZeroMQ (
https://github.com/rpav/ZMQ4L/blob/master/src/autowrap.lisp): достаточно было исключить ограниченный набор системных заголовочных файлов. Если не исключать, просто обёртка будет больше; если время компиляции становится проблемой, она решается cl-plus-c из состава autowrap.
> даже просто разбор header'ов имеет свои грабли, требуется доводка руками
Требуется осилить cffi-grovel. Ну или озвучь его недостатки
Идея глупая и ненужная, на мой взгляд. Языки во-первых разные, во-вторых для каких-то задач для угшечного питона проще написать обертку для библиотеки на C, а для CL правильнее будет реализовать подобную функциональность на самом CL.
Биндинг имеет смысл писать в том случае, когда на другом языке уже есть решение куда лучшее, чем нежели автор писал сам, тратя своё время. Как биндинги к gtk, например. В этом случае имеет смысл потратить время и написать нормальный биндинг самому, нежели чем доверить дело генератору (тем более в случае с gtk есть ихний introspection, который должен и так автоматизировать большую часть работы). Также бывают случаи, когда нужен биндинг к самодельной библиотеки, которая будет делать всю низкоуровневую фигню для вашей библы на CL (как iolib и libfixposix), но это не относится к теме.
Сама по себе цель "поднять уровень полезности лиспа как платформы" не имеет смысла. Должна быть практическая задача и её решение в виде библиотеки или программы на CL. Чем больше таких задач и их решений в виде кода -- тем платформа платформнее, а язык полезнее и нужнее. Всё, что мы имеем в лисп-коммьюнити в России -- это этот полумертвый сайт + 2-3 разрозненных человека, которые могли бы подсказать советом. Мораль такая -- никакие биндинги народ в лисп не заманят, и наоборот -- был бы народ, были бы даже не биндинги, а нормальные полноценные библиотеки (кроме тех случаев, где биндинги действительно нужны).
Вот какая цель у автора поста? Он задолбался уже писать биндинги руками или просто хочет over 9000 сомнительного качества биндингов, сгенерированных его скриптом? Сомневаюсь, что первое -- не такое это уж и частое дело
Я пользовался cffi-grovel-ом. Но не в курсе, работает ли он под виндой и под лиспворксом, для примера?
По целеполаганию дискутировать это здорово, но не имею временных ресурсов.
Мы живём в свободном мире, каждый имеет право полагать свои цели и считать чужие цели глупыми.
Про практическую задачу - я как раз такую решил.
https://bitbucket.org/budden/cl-stirling-engine
Причём это не очередной mp3 плеер или ORM, каких сотни и тысячи. Программа в общем-то наиболее
развитая из всех известных мне опенсорсных программ для этой задачи. И кстати, в ней вовсе
нет биндингов, но я не уверен, что это пошло ей на пользу.
Сейчас у меня два пользователя, которые ни бумбум в лиспе, а один из них ещё и не знает Русский язык.
Они задают вопросы. Послать их жалко, отвечать некогда. Если они осилят программу, это будет значить,
что я привлёк в нашу секту двоих.
>Но не в курсе, работает ли он под виндой и под лиспворксом, для примера?
Нет, совсем не в курсе. Или это риторический вопрос? ))
> По целеполаганию дискутировать это здорово, но не имею временных ресурсов.
А вот делать что-то, что никому кроме тебя не будет нужно -- это куча времени!
А что в твоей программе делается? Какое-нибудь уравнение теплопроводности считается? Или какие-нибудь напряжения, которые в этом двигателе возникают? А гуя там много?
Кстати, зря ты думаешь, что декодирование (а тем более кодирование) звука -- это сильно проще. Просто это хорошо объезжено, в отличие от твоей задачи.
Нет, не риторический вопрос. Винда, наверное, будет и дальше нужна.
Программа считает газовый контур. Сколько подводится тепла, какие гидр.сопротивления,
и какая будет индикаторная мощность и КПД движка. Это основная сложность стирлинга, тут без программы малореально что-либо сделать.
Разве только копировать то, что уже сделано. Плюс она считает механические потери. Гуя там ноль, графики выплёвывает
в файл и дальше говорит операционной системе их показать, а результаты печатает в *standard-output*. Лично мне этот гуй не нужен,
мне удобнее defparameter в коде поменять.
Сложность не играет роли. Просто если задача уже один раз решена, то её новое решение никому не нужно, кроме
самого велосипедостроителя. А моя программа нужна (узкому кругу маргиналов, строящих двигатель стирлинга) и она существенно
превосходит другие опубликованные программы. Естественно, инженерные фирмы, которые строят подводные лодки и ещё
что-нибудь, пишут для себя гораздо более мощные программы, но они их не выкладывают в интернет :)
> Просто если задача уже один раз решена, то её новое решение никому не нужно, кроме
самого велосипедостроителя.
Не совсем так. Иначе бы у нас была 1 ОС, 1 браузер, 1 плеер итд.
Ещё последний вопрос по твоей проге: в каком виде и какие исходные данные она получает? Конкретно в этой области я полный дилетант, но можно было бы попробовать её портануть на sbcl just for lulz
Не знаю, как в битбукете дать конкретный файл, может
вот так получится?
Поскольку часть параметров вычисляется исходя из других параметров, для их задания
нет ничего лучше, чем лисповый скрипт.
Ну и затем, если тебе нужно узнать, что означает та или иная переменная и что ей присвоено,
то find-source к твоим услугам. Т.е. я не думаю, что гуй здесь что-то улучшит.
Далее есть ещё задача оптимизации, когда ты меняешь параметры и ищешь наилучший вариант.
Тут опять же гуй для ввода параметров ни к чему.
Но в целом я очень заинтересован в переводе на SBCL. Сам по себе cl-stirling-engine довольно мал
и не так сложен. Хотя блин 400 кб без примеров.
Но всё упирается в том, что надо портировать
http://code.google.com/p/def-symbol-readmacro/
А этот проект богомерзок. У любого лиспера при его виде сжимаются кулаки и возникает желание сжечь автора на костре.
Я даю 5 против одного, что и у тебя такое желание возникнет. Но страшно не то, что он богмерзок - он ещё и большой по объёму
(600 кил) и нетривиальный (запрашивает environment имплементационно-зависимым способом).
Ну кстати при портировании библиотеки на SBCL половину фич можно просто выкинуть, т.к. они имеют отношение к среде разработки,
а не к языку. Хотя некоторые вещи нужны. Например, я добавил в mode line умение понимать переменную system и readtable.
Это уже скорее вопрос к емаксу и SLIME, а не к лиспу.
Собственно, сам cl-stirling-engine должен быть переносим и не требовать перевода.
Блин, ну ты наворотил)) Ну собственно не удивительно, потому как помню, что вычисления на CL делать - жуткий ад, и я сам городил ридер макросы итд. Ну посмотрю, смогу ли что сделать, но не обещаю ничего
Да там не очень сложно вроде было. Не знаю, откуда столько кода набежало :)
Тесты там, то-сё.
А кто-нибудь игрался с clpython? Можно ли построить на нём демонстрацию на тему "лисп рвёт питон по быстродействию"?
Ну, как хотите, а я всё же хочу попробовать взять биндинги С к питону и сделать из них биндинги С к лиспу.
У меня есть вопросы:
1. Какую ОС и реализацию лиспа взять? Есть три варианта: лиспворкс/винда, SBCL/винда (почти не вариант), SBCL/Linux.
Склоняюсь к последнему. Но если первое работает - будет лучше. Среда лиспворкса удобнее и менее косячная (например, лучше работает
навигация по исходным тектсам, в SBCL/SLIME она откровенно кривая, во всяком случае под виндой).
2. Какую маленькую, но полезную библиотечку от Питона можно взять для начала? Желательно, чтобы там было минимум питоновсокго кода и вообще немного обёрток.
>> 1. Какую ОС и реализацию лиспа взять? Есть три варианта: лиспворкс/винда, SBCL/винда (почти не вариант), SBCL/Linux.
ССL/Windows ?
Не ?
Не. GPL и его разновидности не устраивают.
Обсуждалась в своё время в качестве полезного примера matplotlib. Скачал. Исходников на питоне там 5,8Мб. И ещё 4Мб на С. Неизвестно, сколько сишного кода кроется под этими обёртками. Но понятно, что одним С тут не обойтись, питоновскийТ.е. нельзя сказать, что в них самое ценное - это обёртки к С. Весьма вероятно, что питоновский код не менее важен. Т.е. тут нужен либо интерфейс к питону, либо транслятор с питона.
Извините, осваиваю новую клавиатуру. Я хотел сказать, что если из этой библиотеки взять обёртки, вряд ли они сами по себе будут достаточно ценны, а переписывать 6Мб питоновского кода - большой труд.
>А кто-нибудь игрался с clpython?
Пытался, не взлетело.
А вот
burgled-batteries вполне себе работает. Но psycopg2 не загрузил, упал со странной ошибкой.
Спасибо! Надо посмотреть, что из него можно стащить.
Попробовал приблизиться к реальности.
[code=lisp]
(in-package :cl-user)
(asdf:load-system :pythononlisp)
(defun fff (x) (sin (expt x 2)))
(py::py "execfile('/s2/py/ani2.py')")
[/code]
И вот файл на ani2.py:
[code=python]
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import math
import string
fig, ax = plt.subplots()
#def fff(m):
# return math.sin(m)
def fff(x):
y = pol.LispEval(string.join(['(cl-user::fff ',str(x),')'],''))
return y
x = np.arange(0, 2*np.pi, 0.01) # x-array
y = np.copy(x)
def SetYValues(i):
for row in range(len(x)):
y[row] = fff(x[row]+i/10.0)
SetYValues(0)
line, = ax.plot(x, y)
def animate(i):
SetYValues(i)
# line.set_ydata(np.sin(x+i/10.0)) # update the data
line.set_ydata(y) # update the data
return line,
#Init only required for blitting to give a clean slate.
def init():
line.set_ydata(np.ma.array(x, mask=True))
return line,
ani = animation.FuncAnimation(fig, animate, np.arange(1, 200), init_func=init,
interval=25, blit=True)
plt.show()
[/code]
Не знаю, есть ли в pythononlisp нормальное преобразование типов, поэтому взял строку.
Что можно сказать? Работает.
Но работает странно: не работает из SLIME (SBCL 1.2.7/EMacs 24/Debian 8/Python 2.7 из пакетов).
Вторая странность - после завершения работы sbcl по хорошему не завершается - приходится убивать.
У кого есть идеи?
А в Closure CL под линуксом как? Видел где-то в переписке про попытки скрестить CL и Java, что у SBCL на низком уровне были особенности (точнее не вспомню...).
Python-on-lisp - седая древность, судя по ссылкам. Может с питоном версии 2.5 попробовать (самое современное из того, что перечислено в шапке pythononlisp.lisp)
ccl сработал как часы. Это уже начинает быть похоже на чёрный день календаря. Я думал, SBCL хоть под линуксом допилен.
Не это ли ты имел в виду:
https://common-lisp.net/project/cl-plus-j/
Steel Bank Common Lisp (
SBCL):
CL+J 0.3 does NOT work reliably on SBCL for Linux/x86 or
Linux/x86_64 due to SBCL's inability to handle Unix signals properly
in the presence of foreign threads. The problem is clearly
observable under SLIME since SLIME generates a fairly intense signal
activity through timers. In such a context SBCL crashes into its low
level debugger LDB claiming memory corruption within 20 to 30
minutes of even unattended use. On Windows XP (Win32) SBCL is still
considered "experimental" and does not build with thread
support by default, CL+J 0.3 may work on it but has not been tried.
A port of SBCL on Win64 does not seem to exist officially yet
(2012/07/22) but is in progress according to the SBCL web site.
Да, оно.
Насчёт допиленности - это уже low level вещи, тут особенности реализации во все поля.
Ну не знаю, раз ccl нормально работает, это больше похоже на баги.
Может и баги ведь SBCL "стабильность" не отличается.
SBCL форкнули от CMUCL, который не умеет настоящую многопоточность на нескольких ядрах + тема известна давно + Никодемус пару лет назад много чего пилил в multithreading, даже croudfunding устраивал. Так что это особенность реализации.
А есть ли какой-то способ нормально работать с тредами в SBCL? Допустим, одноядерная машина и взаимодействие с другими программаи только через сокеты? Где вообще про всё это можно почитать?
Не очень понял вопрос. Как я понимаю, SBCL умеет multithreading, но есть ограничения, когда у него в образ загружен foreign код со своими потоками внутри.
Ну ты написал, что CMUCL не умеет многопоточность на нескольких ядрах, вот и возникает вопрос - а где лежит граница между тем, что умеет SBCL после всех допиливаний и тем, что не умеет.
Поскольку проблемы с FFI только что озвучены, ясно, что он умеет не всё. Соответственно, хочется понять, как мне отличить хорошую практику от плохой. То, что будет работать, от того, что не будет.
> То, что будет работать,
make-thread для непрерывных одновременных действий. Не забывая обрабатывать ошибки и выходить нормальным возвратом. Таймеры для прерывистых и асинхронных. Ложат болт на unwind-protect. Для взаимодействия и взаимоуправления sb--concurrency и производные сторонние.
Особенности динамического связывания.
> Поскольку проблемы с FFI
Первоисточник и там же раздел ниже
> Допустим, одноядерная машина и взаимодействие с другими программаи только через сокеты?
Тут скорее сразу смотреть примеры к usocket и асинхронным библиотекам. Более того практически не существует.