LINUX.ORG.RU

Как правильно юзать LuaSocket под оффтопиком?

 , , ,


0

2

Смеркалось.

Написал я как-то программку, хорошую, годную, естественно, под линукс. Написал на Си, для окнорисования использовал gtk и чуть-чуть немножечко Lua для всякого скриптования. Написал и пользуюсь и люди пользуются и вообще все замечательно.

Теперь (начинает играть тревожная музыка) о проблеме: некоторые несознательные граждане пользуются виндой и им нужна эта моя программка на винду: казалось бы, все кроссплатформенное, бери, компиляй под винду и раздавай кактусоедам. И я, собственно, так и сделал: построил билд-машинку, поднял на ней MXE (на редкость ловкая штука), немножечко переколдовал мейкфайл и все замечательно работало до тех пор пока я не подключил в свою lua-логику ейную библиотеку про сокеты.

Оказалось, что виндоус-версия ничего ни про какие луа сокеты не знает (сам луа у меня статически вкомпилен в бинарик основной программы), ну, думаю, не беда: нагуглил скомпиленный уже dll с этими сокетами, сунул в папку с программой – невразумительно ругается (%1 не является приложением вин32), ладно, думаю, я не тупее всех, склонил к себе исходники этих луа-сокетов, изородовал тамошний мейкфайл – стало оно мне dll-ку собирать вместе с проектом, но она (длл-ка) тоже не подхватывается, пишет «не найдена указанная процедура» – сижу, наслаждаюсь информативностью виндовых сообщений об ошибках…

Теперь вопросы:

  1. Как это вообще побеждать?

  2. Как это делается правильно?

  3. Как это можно победить наименьшей кровью? (ну, например, заставлять кактусоедов сначала что-то там себе устанавливать на винду, а потом уже пущать мою прогу)

Линукс тут при том, что программа разрабатывается под линукс, а виндоверсия – приятный бонус в данном случае.

Спасибо!

★★★★★

нагуглил скомпиленный уже dll с этими сокетами, сунул в папку с программой – невразумительно ругается (%1 не является приложением вин32)

Собран под Win32 вместо Win64 или наоборот?

изородовал тамошний мейкфайл – стало оно мне dll-ку собирать вместе с проектом, но она (длл-ка) тоже не подхватывается, пишет «не найдена указанная процедура»

На Windows с давних времён по умолчанию идёт аналог -fvisibility=hidden. Все функции, которые экспортируют из библиотеки, необходимо помечать __declspec(dllexport) или указывать в .def файле. Возможно, забыли сделать что-то из этого, в результате система плагинов, которая работает на dlopen/dlsym/LoadLibrary/GetProcAddress, не может найти функцию luaopen_whatever. Либо дело в этом, либо в symbol mangling.

Как это вообще побеждать?

Попробуйте для Windows собирать и линковать LuaSocket статически. Lua при запуске нужно будет передать функцию luaopen_чтототам, чтобы она создала в памяти библиотеку, но последующие вызовы require уже никуда не полезут.

AITap ★★★★★ ()
Ответ на: комментарий от AITap

Собран под Win32 вместо Win64 или наоборот?

Как это понять по конкретной длл-ке в винде? Я ее достал из сборочки LuaForWindows, примеры из которой вполне себе работают. Правда там 5.1, а у меня 5.3, я сразу не заметил, так что теперь отметается.

Возможно, забыли сделать что-то из этого, в результате система плагинов, которая работает на dlopen/dlsym/LoadLibrary/GetProcAddress, не может найти функцию luaopen_whatever. Либо дело в этом, либо в symbol mangling.

Я не то чтобы забыл: я не знал, спасибо, посмотрю.

Lua при запуске нужно будет передать функцию luaopen_чтототам

О, а вот это отличная идея, ща попробую, спасибо!

pihter ★★★★★ ()
Ответ на: комментарий от pihter

Как это понять по конкретной длл-ке в винде?

Каким-нибудь PEiD или аналогами (включая использование file в линуксе).

Для отладки динамических зависимостей и проблем с ними есть Dependency Walker, он тоже битность показывает.

xaizek ★★★★★ ()
Ответ на: комментарий от AITap

Попробуйте для Windows собирать и линковать LuaSocket статически. Lua при запуске нужно будет передать функцию luaopen_чтототам, чтобы она создала в памяти библиотеку, но последующие вызовы require уже никуда не полезут.

Значить, собрал все объектники, прилинковал к своему бинарю, добавил luaopen_socket_core( L ); следом за своим luaL_openlibs(L); – все вроде бы работает. Насколько я понимаю, оно должно бы в моем луа-состоянии создавать глобальную таблицу socket чтоб require уже никуда не полез – однако, не создает. require лезет, не находит, крашится. При том luaopen_socket_core отрабатывает.

pihter ★★★★★ ()
Ответ на: комментарий от pihter

добавил luaopen_socket_core( L ); следом за своим luaL_openlibs(L); – все вроде бы работает

Почти. Чтобы зарегистрировать модуль в package.loaded, нужно luaL_requiref.

AITap ★★★★★ ()
Ответ на: комментарий от AITap

Спасибо, помогло: залинковалось, работает, но, только на линуксе :)

(кстати, странно, ибо я настолько был обескуражен, что полез в ненастоящую пятницу читать иерусолимскую книгу, там русским по белому написано, что для того чтоб модуль загрузился и, как следствие, прописался в лоадеды, надо вызвать его луаопен_модульнейм и передать луа-состояние… ну да Бог с ним, видимо, надо было еще и главу про взаимодействие с Си прочитать, а я обрадовался что нашел и не прочитал)

тем временем в стане врага, то есть на винде – все еще не работает, при линковке ругается:

./luasocket/inet.o:inet.c:(.text+0x7a): undefined reference to `__imp_getaddrinfo'
./luasocket/inet.o:inet.c:(.text+0x10a): undefined reference to `__imp_getnameinfo'
./luasocket/inet.o:inet.c:(.text+0x1b7): undefined reference to `__imp_freeaddrinfo'
./luasocket/inet.o:inet.c:(.text+0x23f): undefined reference to `__imp_getaddrinfo'
./luasocket/inet.o:inet.c:(.text+0x2ab): undefined reference to `__imp_getnameinfo'
./luasocket/inet.o:inet.c:(.text+0x3fb): undefined reference to `__imp_freeaddrinfo'
./luasocket/inet.o:inet.c:(.text+0x419): undefined reference to `__imp_freeaddrinfo'
./luasocket/inet.o:inet.c:(.text+0x5c3): undefined reference to `__imp_gethostname'
./luasocket/inet.o:inet.c:(.text+0x740): undefined reference to `__imp_getnameinfo'
./luasocket/inet.o:inet.c:(.text+0x900): undefined reference to `__imp_getnameinfo'
./luasocket/inet.o:inet.c:(.text+0xb7f): undefined reference to `__imp_getaddrinfo'
./luasocket/inet.o:inet.c:(.text+0xba0): undefined reference to `__imp_freeaddrinfo'
./luasocket/inet.o:inet.c:(.text+0xd2f): undefined reference to `__imp_getaddrinfo'
./luasocket/inet.o:inet.c:(.text+0xd50): undefined reference to `__imp_freeaddrinfo'
./luasocket/options.o:options.c:(.text+0x1d9): undefined reference to `inet_pton'
./luasocket/select.o:select.c:(.text+0x1e3): undefined reference to `__WSAFDIsSet'
./luasocket/udp.o:udp.c:(.text+0x59c): undefined reference to `__imp_getaddrinfo'
./luasocket/udp.o:udp.c:(.text+0x600): undefined reference to `__imp_freeaddrinfo'
./luasocket/udp.o:udp.c:(.text+0x714): undefined reference to `__imp_freeaddrinfo'
./luasocket/udp.o:udp.c:(.text+0x91e): undefined reference to `__imp_getnameinfo'
./luasocket/udp.o:udp.c:(.text+0xaf1): undefined reference to `__imp_getnameinfo'
./luasocket/wsocket.o:wsocket.c:(.text+0x3f6): undefined reference to `__imp_WSACleanup'
./luasocket/wsocket.o:wsocket.c:(.text+0x436): undefined reference to `__imp_WSACleanup'
./luasocket/wsocket.o:wsocket.c:(.text+0x50f): undefined reference to `__imp_select'
./luasocket/wsocket.o:wsocket.c:(.text+0x56f): undefined reference to `__WSAFDIsSet'
./luasocket/wsocket.o:wsocket.c:(.text+0x61a): undefined reference to `__imp_select'
./luasocket/wsocket.o:wsocket.c:(.text+0xa6c): undefined reference to `__imp_sendto'
./luasocket/wsocket.o:wsocket.c:(.text+0xbfa): undefined reference to `__imp_recvfrom'
collect2: error: ld returned 1 exit status

префикс __, как я понимаю, как раз и означает, что линковщик пытается сыскать сии функции в ДИНАМИЧЕСКОЙ библиотеке, а не в статической? (я просто добавил -lws_32 -lwsocket линковщику). Почему так? Почему на линуксе работает? (я из системы luasokets удалил, в .lua-скриптах теперь не работает) В чем разница?

pihter ★★★★★ ()
Ответ на: комментарий от pihter

префикс __, как я понимаю, как раз и означает, что линковщик пытается сыскать сии функции в ДИНАМИЧЕСКОЙ библиотеке, а не в статической?

Да, ЕМНИП, по адресу __imp_символ во время работы приложения динамический загрузчик расположит прыжок в, собственно, функцию. Это так и должно работать, потому что в Windows поддержка сокетов располагается в отдельном *.dll.

(я просто добавил -lws_32 -lwsocket линковщику).

Хмм, да, так и должно работать. Даже должно быть достаточно -lws2_32 после соответствующих файлов.o (GNU ld чувствителен к порядку объектных файлов.)

Почему так?

А можно взглянуть на то, как собирается командная строка для линковки исполняемого файла?

Почему на линуксе работает?

Там сокеты прямо в стандартной библиотеке C. Это как -lm, только наоборот: на Windows всё и так работает, а на GNU/Linux математические функции надо дополнительно линковать.

AITap ★★★★★ ()

ну так, в оффтопике же свои винсокеты, вестимо видимо надо все это дело еще раз прикомпилять, но уже с мингв реализацие обертки для сокетов, тогда поди все снова станет лепо.

abcq ★★ ()
Ответ на: комментарий от AITap

должно быть достаточно -lws2_32 после соответствующих файлов.o (GNU ld чувствителен к порядку объектных файлов.)

ну что я могу сказать, пейте мой позор до капли: проблема была в этом :) воткнул объектники после либ в линковке

Теперь все работает, спасибо. ( говори куда заслать на пиво! )

// остальным откликнувшимся тоже спасибо!

pihter ★★★★★ ()
Ответ на: комментарий от interrupted

расскажи если есть время. зачем все таки луа засунул в свой софт?

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

Эту программу в прошлый раз (да, я е уже писал и даже не раз :) ) писал на Си+GTK, и с некоторого объема 8-10 тыс строчек писать на си стало затруднительно: внесение даже, казалось бы, небольших изменений требовало внимательного вникания, а уж если чего переделывать задумывал – так это всегда была целая история.

Я Иерусолимского давно прочитал, больно мне понравилось, все мечтал попробовать применить Lua в настоящей задаче и вот, в прошлой еще инкарнации, возник момент когда в программу напросилась система плагинов, Lua для этого подходил идеально, я сделал и мне очень понравилось насколько ловко Lua встраивается в Си – практически стирается грань между языками, при этом Lua показал исключительную скорость в ГУЙовых задачах.

Ну и вот, когда в очередной раз я созрел для переписывания программы с нуля, я решил несколько углубить и расширить предыдущий опыт интегрирования Lua в программу и посмотреть как оно будет в реальной жизни. Я на си реализовал только «API» вида пользователь_провел_мышкой_по_экрану(x,y) или нажата_кнопка_на_клаве( scan_code, shift_state ) - а всю программу написал на Lua. Ну создание всех элементов ГИП-а, прописыавение им колбеков, отрисовка всего на экране и тп. Очень, очень доволен результатом: я получаю всю мощь нативной программы (если мне что-то нужно: я просто реализую это на си и в Lua экспортирую все нужные ручки) и легкость и шолковистость разработки на скриптовом языке. Кроме того, Lua прекрасен: я просто мечтал на нем пописать после прочтения книги и ни на секунду не разочаровался, хотя этот момент, наверное, – дело вкуса. + Кроссплатформенность почти даром (хотя и есть некоторые трудности, как ты видишь, но это мелочи)

это правда упрощает что то?

Без сомнений что-то да упрощает :) Прочитай книгу, там, если отбросить справочную часть, 200 страниц – тебе автор языка подробно расскажет о преимуществах встраивания Lua в свои программы. Лично мой опыт в данном вопросе – сугубо положительный, рекомендую не пожалеть вечерок-другой и ознакомиться

pihter ★★★★★ ()
Ответ на: комментарий от pihter

писал на Си+GTK

Коллеги Иерусалимского из того же университета написали IUP, который хорошо интегрирован именно с Lua. Сам использовал только в небольшом проекте на C (а также попробовал в очень маленьком на Lua), мне понравилось.

IUP работает поверх GTK на Linux и WinAPI на Windows. В планах нативный интерфейс на macOS, но рук для этого явно не хватает. В дистрибутивах IUP не найти: опциональная зависимость canvas draw, например, тащит с собой старую версию libtiff с патчами), а система сборки там самопальная и странная.

AITap ★★★★★ ()
Ответ на: комментарий от AITap

IUP

А я как-то смотрел, но давно, несколько лет назад точно. Не помню что там мне не понравилось, что я решил ГТК. Стоит опять поглядеть?

pihter ★★★★★ ()
Ответ на: комментарий от pihter

Не помню что там мне не понравилось, что я решил ГТК. Стоит опять поглядеть?

Архитектура с тех пор не изменилась: всё, что есть на экране, хранится в памяти в виде дерева. Все атрибуты элементов хранятся в хэш-таблице с ключами-строками и значениями-строками, вплоть до IupSetAttribute(vbox, "MARGIN", "10x10"). Код получается лаконичный (по моим ощущениям, печатать меньше, чем в GTK), но ощущение после себя оставляет странное.

AITap ★★★★★ ()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.