Сейчас пилю игрушку про летающие диски (о чем писал в теме для последнего конкурса). Собственно, опять для прогеров. Собственно, dll-ки, созданные на шарпе и делфи уже работают.
Но вот хотелось бы прикрутить еще и скриптовые языки. Начал с LUA, потому что у Пайтона слишком много различных модификаций, чтобы с наскоку въехать. И вроде бы даже собрал тестовый проект C# + LUA и вроде бы даже нашел, как передавать объекты из одного в другой... Но вот вопрос: а каким-нибудь образом можно создать/запустить скрипт, чтобы он мог в промежутках между вызовами хранить какую-то информацию? Ну, к примеру, какой-нибудь каунтер инкрементить, считая вызовы, или же таймер отслеживать?
Вопрос, в общем-то, теоретический, по сути, можно ли скрипт запустить аля dll? Просто до этого у меня никакого опыта работы со скриптами не было...
Хотя такие вещи как скрипты по уму было бы лучше запускать в отдельном AppDomain с урезанными правами.
Я не уверен, что хранение состояния внутри скрипта не является плохим дизайном. По возможности всегда лучше избегать stateful объектов, но если хочется, то в случае с использованием самого же C#:
1) после генерации сборки из C# скрипта, и загрузки этой сборки в память, статические поля будут хранить своё состояние.
2) после создания объекта из этой сборки, в теории, с ним можно делать что угодно. Т.е. инстанс создан, состояние у него есть, следовательно можно вызывать произвольные методы произвольное число раз.
Как это сделать с Lua, я не знаю, последний раз экспериментировал с этим лет пять назад :-)
Главное при таком подходе не запускать скрипты из разных потоков :-)
Или наоборот, можно упороться и обернуть вызовы каждого скрипта в Task. А внутри скрипта запустить бесконечный цикл)
Спасибо, MeF Dei Corvi!
То есть, я правильно понял из твоего сообщения и поста на стековерфлоу, что для своих целей могу просто описать класс в скрипте, а потом его использовать в основной программе? Потому что по сути именно это мне и надо.
Да, именно так. В базовой реализации, если не заморачиваться с отдельным AppDomain, то произвольное множество файлов или даже наборов строк можно с помощью самого же .NET скомпилировать в отдельную сборку прямо в памяти, и работать с ней так, как если бы на неё была бы ссылка из программы.
Ну, разве что конкретные типы на этапе первоначальной компиляции неизвестны, поэтому, как в примере на stackoverflow, возможно имеет смысл описать некие контракты, по которым основное приложение будет общаться со скриптами.
А вообще, в случае в Lua, наверное, можно сделать объект, который хранит состояние, и просто гонять его туда-сюда между вызовами скрипта?
А вот интересно... Если дллка будет изменять адресное пространство игры-хоста с целью подтасовки\обеспечения выигрыша в свою пользу, это будет считаться легальным в возможных будущих соревнованиях по этой игрушке?
MeF Dei Corvi
Я обязательно на днях соберу пример со stackoverflow, чтобы получше разобраться. Но конечной целью было именно прикрепление скрипта Lua. Собственно, я полагаю, что сам объект, описанный в Lua и будет содержать свое состояние, а уже вызывать его методы будет основная программа.
CoderInTank
В принципе, я считаю, что если сумеешь изменить адресное пространство, то победа заслуженно твоя. :) С другой стороны, написание самого алгоритма - это несколько иная задача. Для нее достаточно знать азы программирования, зато простор для фантазии именно в алгоритмировании неограничен.
Я боюсь, что большинство скриптовых движков не предполагают сохранение состояния между запусками скрипта. Я бы сделал в скрипте один метод, который описывает шаг, в который передаётся доступное состояние окружения, включая словарь "памяти" скрипта. На выходе метод возвращает измененный объект памяти, а также некоторое решение: набор действий, которые необходимо предпринять, и их параметров.
Ну или можно организовать какое-то внешнее хранилище, т.е. сделать методы setTempData/getTempData, которые можно будет вызвать из скрипта, и которые будут менять некоторый объект состояния, хранящийся вне скрипта.
Все эти три недели в свободное время возился с Lua и вот что выяснил(сорри, если я не совсем технически грамотно опишу):
1. Lua таки хранит состояние. Но для всего контекста и в глобальных переменных. Таким образом, если объявить при первом запуске скрипта глобальную переменную, то при всех повторных запусках этого скрипта или других в данном контексте переменная уже будет существовать.
2. Хранить состояние различных объектов можно в глобальной многомерной таблице (GlobalData), выделяя под каждый объект свою строчку.
3. Чтобы конкурирующие объекты или объекты, использующие один и тот же скрипт, не пользовались одними и теми же данными и вообще не могли знать инфу друг о друге, каждой строчке в GlobalData можно присвоить уникальный случайный ключ - что-то вроде GUID.
4. А вот сформированные GUID'ы хранить уже в вызывающей программе и передавать их нужным скриптам при запуске, чтобы они знали, какие данные брать.
Ну и последнее. Как выяснилось, вовсе необязательно каждый раз запускать и прогонять полностью скрипт. Можно прогнать его один раз, сохранив имеющиеся в нем функции в вызывающей программе, а потом вызывать их по мере надобности. Но вот тут не 100%, потому что LuaInterface у меня пока не очень стабильно работал.