Перейти к контенту
Malandrinus

Язык Lua. Общие вопросы программирования

Рекомендуемые сообщения

С чего начинать и где взять.

 

Установка Lua:
http://www.amk-team.ru/forum/index.php?showtopic=11584&p=629106

 

Руководство «Программирование на языке Lua», третье издание:
http://www.amk-team.ru/forum/index.php?showtopic=11584&p=905308

Изменено пользователем Kirgudu
Ссылка на комментарий

malandrinus,

Я же не говорю что перебор это панацея. Сам бы наверное поступил незатейливо.

Был задан несколько пространный вопрос. Зная что нужно, на зная точно для чего, достаточно тяжело сказать как.

Ведь я не зря вначале сказал, - "Нужно знать откуда и при каких условиях запрашивается это имя".

Вот и получилось, что количество вариантов наверняка оказалось больше чем ожидал "заказчик".

Варианты. Только и всего.

 

 

Ссылка на комментарий

> Мне интересно, в связи с чем потребовалось узнавать имя модуля? У меня самого такая задача тоже возникала, но настолько редко, что я бы не заморачивался на автоматизацию даже при отсутствии штатных стредств. <

 

У меня для вызова функций есть спец. функция которая принимает имя скрипта, имя функции + параметры.

Мне нужно было в пределах одного скрипта вызвать его функцию по её имени, соответственно я должен указать имя скрипта, и имя функции. Имя функции у меня есть, а имя скрипта я бы мог написать вручную, но вдруг потом кто то скрипт переименует?

Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О

Мастер аномалий на свою заднюю точку.

Ссылка на комментарий

malandrinus,

Чего не приведешь пример с getFS()? Или пускай сами смотрят....

А перебор _g, ну это мягко скажем.. вывернутся наизнанку, что-бы пощекотать ухо....

script_name, debug.. И не более.. А что, правленая луа и длл, и всё в порядке....

у меня даже в своё время был написан самопальный трейсер на основе debug.get_info. И нормально работал...

кстати, get_fs, самый гибкий и удачный вариант.. Если нужно из вне узнать имя.. А из строки скрипта где он исполняется script_name, или debug.get_info. Но последнее считаю мелким извратом.

Изменено пользователем Unnamed Black Wolf
Ссылка на комментарий

Занимаясь кое-какими своими делами, случайно вспомнил (точнее сказать наткнулся) на довольно старую статью.

В своё время воспринял её как аксиому и...пользовался.

(Далее для начинающих)

Но на само то деле в ней описываются действительно полезные советы. Сейчас я её в сети не найду (или не хочу искать, т.к. сохранил у себя) поэтому процитирую некоторые моменты.

Вопросы производительности

 

При разработке программ на Lua нужно иметь в виду, что компилятор этого языка не обладает широкими способностями по оптимизации. С другой стороны, интерпретатор Lua реализован очень эффективно и чаще всего обеспечивает весьма приличную скорость работы. Если же тебе нужна сверхвысокая производительность, ты должен сам следить за тем, чтобы в коде не было множества лишних конструкций. Добиться этого будет легче, если будешь придерживаться нескольких простых правил при написании кода на Lua (подробнее о подходах к оптимизации кода на Lua — в материалах, опубликованных в Lua Us-ers Wiki).

 

Доступ к локальным переменным в Lua несколько быстрее, чем к глобальным. Если требуется интенсивный доступ к глобальной таблице, функции или корутине, лучше завести локальную, присвоить ей значение глобальной и только потом начинать использовать. Эта техника не несет накладных расходов на копирование, так как в Lua данные таких типов копируются как ссылки, а не как значения.

 

По возможности в коде, критичном по производительности, не создавай множество объектов Lua, управляемых сборщиком мусора. Такие объекты создаются при склеивании строк, вызове конструкторов таблиц (например при вызовах функций с переменным числом аргументов), при объявлении любых функций, при выполнении команд dofile/dostring.

 

Компилятор Lua способен выполнять элементарную оптимизацию. Например, он оптимизирует простые выражения с участием переменных и констант. Не обязательно заменять, скажем, выражение

 

= 2 * 34567 + b

на

a = 69134 + b.

 

Перевод скриптового кода в код на C++ — один из действенных методов оптимизации. Если тебе вдруг показалось, что какой-то участок кода на Lua нужно подвергнуть интенсивной оптимизации, может быть, ты обнаружил первый сигнал к тому, что этот кусок кода нужно переписать на C++.

 

Заботясь о производительности кода, остерегайся преждевременной оптимизации. По возможности соблюдай рекомендации по написанию оптимального по производительности кода — писать гарантированно медленный код не стоит. Однако, как известно, затраты, скажем, на оптимизацию куска кода, который выполняется не более 1% времени, не уменьшат временные затраты на выполнение программы больше чем на 1%.

 

Сначала реализуй код самым удобным (по твоим ощущениям) способом. Если понадобится, собирай статистику с помощью таких инструментов, как Lua Profiler (www.keplerproject.org/luaprofiler). И оптимизируй только то, что действительно должно быть оптимизировано.

Обработка ошибок

 

Важно помнить, что при небрежном отношении к обработке ошибок в Lua, после возврата ошибки из lua_pcall(), скриптовая система может оказаться в невалидном состоянии.

 

Безопаснее всего (по крайней мере, в стадии активной разработки) прекращать выполнение программы при возникновении ошибок в скрипте. Естественно, это не относится к консольному интерпретатору, в котором для комфортной работы нужно обеспечивать толерантность к возможным ошибкам и опечаткам. Тем не менее желательно принимать меры к тому, чтобы ошибки в коде, выполняемом с консоли, не приводили к неявной «порче» игрового мира.

ПРИ ВОЗНИКНОВЕНИИ ОШИБКИ В ФУНКЦИЯХ НА LUA ВМЕСТО ВЫЗОВА БИБЛИОТЕЧНОЙ ФУНКЦИИ ERROR() ВОЗВРАЩАЙ NIL И ТЕКСТ СООБЩЕНИЯ ОБ ОШИБКЕ.

 

ФУНКЦИИ, КОТОРЫЕ МОГУТ ВЫЗВАТЬ ERROR(), ВЫЗЫВАЙ (ГДЕ ВОЗМОЖНО) ЧЕРЕЗ БИБЛИОТЕЧНУЮ ФУНКЦИЮ PCALL(), ДЛЯ ЧЕГО ЛУЧШЕ ИСПОЛЬЗОВАТЬ ИДИОМУ PROTECT, ОПИСАННУЮ В СТАТЬЕ ДИЕГО НЕХАБА (DIEGO NEHAB) FINALIZED EXCEPTIONS (www.lua-users.org/wiki/FinalizedExceptions). ТАКЖЕ ПОЛЕЗНО ПОЛЬЗОВАТЬСЯ ИДИОМОЙ NEWTRY (СМ. ТУ ЖЕ СТАТЬЮ).

 

ПРОВЕРЯЙ ПЕРЕДАННЫЕ ФУНКЦИИ ПАРАМЕТРЫ НА NIL. ЕСЛИ, НАПРИМЕР, ФУНКЦИЯ, ОБЪЯВЛЕННАЯ С ТРЕМЯ ПАРАМЕТРАМИ, ВЫЗЫВАЕТСЯ С ДВУМЯ, ТО ТРЕТЬЕМУ ПАРАМЕТРУ БУДЕТ ПРИСВОЕН NIL.

 

ЕСЛИ ТВОЯ ФУНКЦИЯ РАБОТАЕТ С ГЛОБАЛЬНЫМИ ДАННЫМИ, ОСОБЕННО С ОПИСАНИЯМИ УРОВНЕЙ, ТЕКСТАМИ ДИАЛОГОВ И Т.П., ПО ВОЗМОЖНОСТИ ПРОВЕРЯЙ ЭТИ ДАННЫЕ НА NIL.

 

ОЧЕНЬ ЧАСТО ОШИБКИ ВОЗНИКАЮТ ИЗ-ЗА ТОГО, ЧТО ПРОГРАММИСТ ЗАБЫЛ НАПИСАТЬ КЛЮЧЕВОЕ СЛОВО LOCAL ПЕРЕД ПЕРВЫМ ПРИСВАИВАНИЕМ ЛОКАЛЬНОЙ ПЕРЕМЕННОЙ И ЗАТЕР ТАКИМ ОБРАЗОМ ГЛОБАЛЬНУЮ. СЛЕДИ ЗА ОБЛАСТЬЮ ВИДИМОСТИ ТВОИХ ПЕРЕМЕННЫХ. В НАЗВАНИЯХ ГЛОБАЛЬНЫХ ПЕРЕМЕННЫХ ИСПОЛЬЗУЙ УНИКАЛЬНЫЙ ПРЕФИКС, НАПРИМЕР G_. ПРИМЕНЯЙ ИНСТРУМЕНТЫ ТИПА LUA LINT ДЛЯ ПРОВЕРКИ ИСПОЛЬЗОВАНИЯ ГЛОБАЛЬНЫХ ПЕРЕМЕННЫХ. В ДИСТРИБУТИВ LUA 5.1 ВХОДИТ ПРИМЕР НА LUA, КОТОРЫЙ НАСТРАИВАЕТ МЕТАТАБЛИЦУ ТАБЛИЦЫ, СОДЕРЖАЩЕЙ ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ (”_G”), ТАКИМ ОБРАЗОМ, ЧТО ПРИ ДОБАВЛЕНИИ ИЛИ ЧТЕНИИ НЕЗАРЕГИСТРИРОВАННЫХ ГЛОБАЛЬНЫХ ПЕРЕМЕННЫХ ВО ВРЕМЯ ВЫПОЛНЕНИЯ СКРИПТА ВЫДАЕТСЯ СООБЩЕНИЕ ОБ ОШИБКЕ.

 

СТАРАЙСЯ МИНИМИЗИРОВАТЬ ИСПОЛЬЗОВАНИЕ ГЛОБАЛЬНЫХ ПЕРЕМЕННЫХ. СОБЛЮДАЙ МОДУЛЬНОСТЬ КОДА. СЧИТАЕТСЯ ХОРОШИМ ТОНОМ, ЕСЛИ ОДИН МОДУЛЬ СОЗДАЕТ ТОЛЬКО ОДНУ ГЛОБАЛЬНУЮ ПЕРЕМЕННУЮ. ПОДРОБНЕЕ О ПОДХОДАХ К ОРГАНИЗАЦИИ МОДУЛЕЙ В LUA МОЖНО ПРОЧИТАТЬ В LUA TECHNICAL NOTE 7: MODULES & PACKAGES РОБЕРТО ИЕРУСАЛИМСКОГО (www.lua.org/notes/ltn007.html).

 

ИЗБЕГАЙ СОЗДАВАТЬ НА СКРИПТОВОМ ЯЗЫКЕ СЛИШКОМ СЛОЖНЫЕ СИСТЕМЫ. ДИНАМИЧЕСКАЯ ТИПИЗАЦИЯ И ПРОЧИЕ ОСОБЕННОСТИ, ПРИ ВСЕМ СВОЕМ УДОБСТВЕ, ПЛОХО ВЛИЯЮТ НА СТАБИЛЬНОСТЬ, НАДЕЖНОСТЬ И ПРОИЗВОДИТЕЛЬНОСТЬ КОДА. СКРИПТОВЫЕ ЯЗЫКИ ВООБЩЕ И LUA В ЧАСТНОСТИ ХОРОШИ ДЛЯ «СКЛЕЙКИ» И НАСТРОЙКИ ФУНКЦИОНАЛЬНОСТИ ИГРОВОГО ДВИЖКА. ЕСЛИ ТЫ ВИДИШЬ, ЧТО КАКОЙ-ТО МОДУЛЬ НА LUA СТАНОВИТСЯ СЛИШКОМ СЛОЖНЫМ, ПОСТАРАЙСЯ ПЕРЕНЕСТИ ЕГО ФУНКЦИОНАЛЬНОСТЬ НА C++, ОСТАВИВ LUA ТОЛЬКО ВЫСОКОУРОВНЕВОЕ УПРАВЛЕНИЕ ЭТИМ МОДУЛЕМ.

 

Управление памятью

 

Язык Lua автоматически управляет памятью при помощи сборщика мусора (garbage collector): интерпретатор периодически вызывает сборщик мусора, удаляющий объекты, для которых была выделена память (таблицы, userdata, функции, потоки и строки) и которые стали недоступными из Lua («мертвые» объекты).

 

Интерпретатор Lua задает предел объема памяти (threshold), занимаемого данными. Как только занятый объем достигнет этого предела, запускается алгоритм, освобождающий память, занятую накопившимися «мертвыми» объектами. Затем устанавливается новый предел, равный двухкратному объему памяти, занимаемой после очистки.

 

Чтобы запустить сборку мусора немедленно, нужно программно установить предел занимаемой памяти в 0 (вызвав lua_setgcthreshold() из C или collectgar-bage() из Lua). Чтобы остановить сборку мусора, устанавливаем этот предел в достаточно большое значение.

 

Замечено, что в некоторых случаях память, занимаемая данными Lua, проявляет тенденцию к разрастанию, что может негативно сказаться на производительности программы. Чтобы избежать этого, лучше периодически вызывать сборку мусора принудительно.

 

При написании программ на Lua обязательно учитывай то, каким образом интерпретатор Lua управляет распределением памяти. Сборка мусора — относительно затратная по производительности операция (используется алгоритм non-incremental mark and sweep). Она инициируется автоматически, когда объем выделенной памяти превышает двукратный объем памяти, оставшейся выделенной после предыдущей сборки мусора (объем выделенной памяти, при превышении которого произойдет следующая сборка мусора, также можно задавать программно). Значит, фактически, в достаточно большой динамической системе сборка мусора может быть запущена в произвольный момент времени, вызвав просадку по производительности. Чем больше памяти выделено под объекты Lua, тем дольше происходит сбор мусора.

 

Итак, если ты, например, читаешь в Lua данные из файла построчно и склеиваешь их в одну строку линейно, скорее всего, процесс будет продвигаться страшно медленно: после каждой следующей операции склейки объем занятой памяти, как минимум, удваивается и, соответственно, запускается процесс сборки мусора.

 

Код создает новую строку (и присваивает ее переменной some_string), а строка, хранившаяся в some_string до склейки, остается в памяти до следующей сборки мусора:

 

some_string = some_string .. "a"

 

Такая проблема и способы ее решения описаны в статье Роберто Иеруса-лимского Lua Technical Note 9: Creating Strings Piece by Piece (www.lua.org/notes/ltn009.html). В Lua 5.1 реализована инкрементальная сборка мусора, позволяющая распределить нагрузку по производительности от процесса сборки мусора во времени

 

Изменено пользователем Gun12
Ссылка на комментарий

Если кто ещё интересуется оптимизацией скриптов, я все-таки реализовал поддержку многопоточности. Теперь скорее даже интересно, какие именно задачи можно считать дополнительной нитью. Как я понимаю у большинства игроков сейчас двух-ядерные процессоры, массовый параллелизм в жизнь не провести?

Плавайте поездами аэрофлота!

Ссылка на комментарий

аlреt

Неужели ты считаешь, что такая информация может быть проигнорирована? :)

Можно подробности?

Это только для контекста Сталкера, или для luа в целом?

Ссылка на комментарий

Gun12

Это для скриптов сделано, и подразумевается что доступны все функции предоставляемые luacap (некоторые при этом опасно вызывать, если они обращаются к движку), и все функции пользовательских DLL.

Применение многопоточности не ограничивается ускорением рассчетов, можно для разных асинхронных запросов вроде листания толстых файлов (в поисках некой инфы), или даже работы с сетевыми сокетами - позволит реализовать натуральный чат, или пополнение новостей/анекдотов с некоего сервера для тех кому фишки интересны. Суть в том, что выделенные нитки помогают выполнять тяжелые по времени атомарные операции, не приводя к явственным лагам в игре.

Реализовать поддержку выделенных нитей можно и в проекте RvP, однако у меня есть в перспективе важное преимущество - можно будет запускать дочерний процесс аналогично как нитку, через достаточно быстрый IPC с ним сообщаться в плане обмена данными. А отдельный процесс уже штука серьёзная, это как минимум лишние 2Гб памяти для какой-либо БД или ещё чего-нить.

Плавайте поездами аэрофлота!

Ссылка на комментарий

alpet, очень интересная инфорамция и обнадеживающая. Обязательно попробую потестровать и проверить наличие многопоточности именно в игре.

Однако ... халь, что по сути подобное носит "новостной характер", т.к. без хоть каких-то кодов/исходников остается или только использовать то что доступно или, засучив рукава, торить новый путь по указанному курсу ... чтобы иметь возможность подстраивать под иные версии и варианты расширения движка.

 

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

Можно ли стандартными средствами Lua, доступными в чистом ЧН, открыть текстовый файл на жёстком диске?

Хочу до принудительного вылета через abort() открывать на компьютере пользователя текстовый файл с логом игры.

 

_________

 

Или хотя бы как скопировать текст в буфер обмена средствами Lua?

Изменено пользователем *Shoker*

Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О

Мастер аномалий на свою заднюю точку.

Ссылка на комментарий

*Shoker*, в Lua имеется пространство io, которое доступно в версии игры CS (ЧН).

1. Тот же мод "Faction commander" на полную катушку использует запись в свои конфиг и лог.

2. Странно видеть подобный вопрос от того, кто в своем моде использует (по сути) это:

function save_to_file(filename)
    local fname = getFS():update_path("$game_saves$", filename..".msf") --/#~#
    local file = io.open( fname, "w" ) --/#~#
    if file then
...

Если же вопрос не про открытие/использование своего файла со своими сообщениями, а о том, чтобы (и) "штатые" строки лога сохранять в каком-то вторичном файле помимо "штатного" лог-файла - то так и нужно писать об этом. И вопрос бы не в топик по Lua, а в топик по ковыряниям в файлах игры ...

Средств Lua для подобного нет, т.е. 'что и куда' указано - 'то и туда' и пишет. Консоль - это уже не Lua, а движек игры.

Т.о. без стороннего модуля, который бы мониторил "штатный" лог (консоль) и дублировал бы куда захотелось - не обойтись.

 

P.S. Ну тогда ты точно топиком обшибся. Средствами Lua можно многое делать, в том числе и тебе потребное, но ... тебе же нужно ИЗ ИГРЫ, т.е. и не самим Lua, а его кастрированным куском и не столь Lua, сколь абы чем лишь бы ... покомандовать на компе пользователя без его участия (хотя бы и в благих целях).

Сорри, удаляюсь, подобные задачки в игре считаю моветоном.

Изменено пользователем Artos

"Но иногда найдется вдруг чудак, этот чудак все сделает не так ..."© Машина времени

Ссылка на комментарий

Цель в том чтобы средствами Lua выполнить программу на компьютере пользователя, например открыть текстовый файл с логом или запустить на крайний случаи какой нибудь exe.

Вариант с io.open это совсем не то.

 

К сожалению ничего подходящего тоже не нашёл.

Единственная боле\менее вменяемая функция для "общения" с пользователем это os.execute(), которая теоретически может работать с командной строкой системы, но в сталкере при её использовании либо ничего не происходит, либо зависает (видимо в случаи возврата ошибки), хотя os.exit() работает, и область видимо экспортирована в Lua.

 

 

Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О

Мастер аномалий на свою заднюю точку.

Ссылка на комментарий

*Shoker*,

os.execute работает без проблем. Путь верно задаёшь?

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

Я с ним честно говоря ни разу не работал. Как в него правильно вводить я не знаю.

Проштудировал гугл и справочник. Пробовал такие варианты:

 

os.execute("launcher.exe") - лаунчер это приложение в папке bin (проверял на сталкере), игра виснет на 2-3 секунды, потом всё ок, но ничего не открывается

os.execute("echo hello") - нашёл на каком то форуме, не зависает но в командную строку ничего не выводит, даже если она открыта. Я так понял из описания что эта execute работает с командной строкой.

os.execute("cmd.exe") + параметры всякие ещё - либо ничего либо чаще всего просто зависала игра.

os.execute("mmmmm") - зависает, видимо из за возврата кода ошибки

 

Единственное что не пробовал пока только полный путь указывать.

Изменено пользователем *Shoker*

Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О

Мастер аномалий на свою заднюю точку.

Ссылка на комментарий

*Shoker*,

os.execute("cmd.exe") + параметры всякие ещё - либо ничего либо чаще всего просто зависала игра.

это не игра зависает. Это открывается консоль и фокус окна передается туда. Тоесть консоль открыта и ты с ней работаешь. Но при этом игра включена на весь экран.

 

os.execute("launcher.exe") - лаунчер это приложение в папке bin (проверял на сталкере), игра виснет на 2-3 секунды, потом всё ок, но ничего не открывается

скорей всего оно выполнилось и закрылось

Vita sine libertate, nihil

Vita sine litteris - mors est

Ссылка на комментарий

RvP

Игра у меня всегда открыта в оконном режиме. но при использовании execute у меня ни визуально, ни в процессах ничего не происходит. Это просто выглядит как зависание. :(

 

скорей всего оно выполнилось и закрылось

В этом приложении есть интерфейс но он не отобразился. А что ещё там могло выполниться я даже не знаю...

Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О

Мастер аномалий на свою заднюю точку.

Ссылка на комментарий

*Shoker*,

Единственное что не пробовал пока только полный путь указывать.

Самое главное и не попробовал =) Если ты указываешь просто имя, то файл берётся по текущему пути. А ты его знаешь? Используй класс FS для получения полного пути по относительному от каталога игры или напиши сам руками.

 

Плагины Total Commander для работы с игровыми архивами:

Архиваторный плагин (для работы с одиночным архивом): link1 link2

Системный плагин (для распаковки установленной игры): link1 link2

 

Ссылка на комментарий

RvP, malandrinus

Спасибо! И впрямь заработало. Консоль и моё стороннее приложение открывается. :)

_____

 

Тока вот не разобрался как что то напечатать в в командную строку с помощью os.execute

Хочется не просто открыть её а вывести сообщение. Я конечно могу .bat файл зарание готовый использовать но всё же интересно.

 

_____

 

Отлично, с помощью execute можно и текстовые файлы открывать. :rolleyes:

Ещё раз спс.

Изменено пользователем *Shoker*

Можно просто Shoker, форум АМК съел моё старое имя и не хочет отдавать о_О

Мастер аномалий на свою заднюю точку.

Ссылка на комментарий

*Shoker*, возможно тебе будет удобней сделать свою dll и require ее?

 

 

Изменено пользователем RvP

Vita sine libertate, nihil

Vita sine litteris - mors est

Ссылка на комментарий

*Shoker*

ИМХО, гораздо интереснее смотрится решение твоего вопроса с использованием pipe.

--============================================================
-- Открыть файл
io.popen("D:\\name_file.txt")
--============================================================
-- Чтение из файла построчно
for line in io.popen("type D:\\name_file.txt"):lines() do
    -- чего-то там делаем со строкой "line"
end
--============================================================
-- Запуск CMD и вывод в него содержимого файла
io.popen('start cmd /k type D:\\name_file.txt')
-- или сообщения
io.popen('start cmd /k echo message')
--============================================================
-- Получение результата работы команд (напр. 'echo', 'dir')
local f = io.popen('echo message',"r")
local s = f:read("*a")
print(s)

-- Получение из директории С имён файлов с расширением *.txt
for line in io.popen("dir c:\\"):lines() do
    if line:match("%.txt$") then
        -- чего-то там делаем со строкой "line"
    end
end

 

 

Ссылка на комментарий

Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

Создать аккаунт

Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!

Зарегистрировать новый аккаунт

Войти

Есть аккаунт? Войти.

Войти
  • Недавно просматривали   0 пользователей

    Ни один зарегистрированный пользователь не просматривает эту страницу.

AMK-Team.ru

×
×
  • Создать...