ITCS - Lua и C/C++/C#. Часть 1 - ПРОГРАММИРОВАНИЕ
Сегодня: Понедельник, 05.12.2016, 23:37 (МСК)| Здравствуйте, Гость| Мой профиль | Регистрация | Вход | RSS

Военные технологии на пользовательском рынке

Визуальная среда Flowstone

Роботы и экзоскелеты

Google Chrome. Таким должен быть браузер

Плагины Sonnox Oxford
Главная » ПРОГРАММИРОВАНИЕ

Lua и C/C++/C#. Часть 1

06.09.2011

Интеграцию Lua с C/C++/C# было решено вынести в отдельную серию материалов. Сам язык является по существу универсальным, а наиболее частое его использование — в игровых проектах. Всю вводную часть по Lua, его основному синтаксису, вы можете прочесть в цикле материалов «Lua для игр и не только». Сейчас же углубимся в узкоспециализированные ниши. 
Сегодня мы начнем с самых азов интеграции, инсталлируем Lua и сделаем несколько простых примеров для C#.

Для урока в этой части вам понадобится Visual C# или же MSVS (Microsoft Visual Studio) 2003 и выше (я все буду показывать на 2008), а также LuaInterface (вариант для .NET CLR) скачанный с http://luaforge.net/projects/luainterface. Распакуйте его в удобную для вас папку, но при этом, чтобы вы не смогли ее случайно удалить. 


Создаем новое приложение


Итак, первым делом создаем новый проект Visual C# (Console Application), назовем его LuaTest01. 



После того как базовая модификация загружена, нам нужно прикрепить LuaInterface.dll. Делается это через Solution Explorer: нажимаете правую кнопку мыши над References, в открывшемся контекстном меню выбираете пункт Add Reference, в результате чего появляется одноименное окно. 



В нем переходите на закладку Browse (в 2003-й это делается отдельной кнопкой) и указываете путь к библиотеке LuaInterface.dll, которая находится в директории Built той папки, в которую вы распаковали LuaInterface. 



В результате проведенных действий у вас должна появиться новая запись в пункте Reference. Дело сделано. 

Теперь переходим непосредственно к файлу с кодом и прописываем в первые строки: 

using System;
using LuaInterface;

namespace LuaTest01
{
class Program
{
static void Main(string[] args)
  {
  }
}
}

Теперь в функцию Main () пропишем небольшой фрагмент кода, который, кстати, дается в документации по LuaInterface, но в данном случае сделаем и некий вывод результатов в консольном окне. 

static void Main(string[] args)
{
Lua lua = new Lua();
lua["num"] = 2;
lua["str"] = "a string";
double num = (double) lua["num"];
string str = (string) lua["str"];
Console.WriteLine("str:" + str + "\tnum:" + num);
Console.ReadLine();
}

Итак, если переводить строка за строкой, сначала мы запускаем интерпертатор Lua, затем создаем две глобальные переменные «num» и «str» и присваиваем им некие значения. После мы считываем и преобразуем для С# значения этих глобальных переменных и выводим на экран консольного окна. Нужно отметить, что сам LuaInterface предназначен, прежде всего, для обеспечения взаимодействия/совместимости между двумя языками, а лучше сказать между языком Lua и определенной платформой. В частности, в нашем случае мы используем библиотеку для .NET CLR. CLR (Common Language Runtime) — это общеязыковая исполняющая среда платформы .NET, также параллельно с этим понятием часто используются CTS (Common Type System — общая система типов) и CLS (Common Languages Specification — общеязыковая спецификация). В принципе, все это относится больше к .NET, и в нашем случае глубоко копать мы не будем. Главное понимать, что есть исполняющая среда CLR, имеется общая система типов, а LuaInterface обеспечивает полноценную трансляцию и конвертацию. В рамках приведенного выше кода был осуществлен автоматический перевод string в System.String и number в System.Double. 


DoString


Теперь, давайте, немного исправим наш пример, используя команду DoString(), в рамках которой можно вставлять исполняемые блоки кода (или как их еще называют порциями — chunks) на Lua:

static void Main(string[] args)
{
Lua lua = new Lua();
lua.DoString("num=2");
lua.DoString("str='a string'");
double num = (double) lua["num"];
string str = (string) lua["str"];
Console.WriteLine("str:" + str + "\tnum:" + num);
Console.ReadLine();
}

Как видите ситуация никак не изменилась с одной лишь разницей, что мы стали использовать порции кода Lua. 




RegisterFunction


В исполняемой среде класс Lua имеет метод RegisterFunction, позволяющий регистрировать методы CLR как глобальные функции Lua. В качестве первого ее аргумента указывается имя, которое вы бы хотели присвоить этой функции в рамках Lua. Второй аргумент — это объект или класс, содержащий метод, а третий аргумент — непосредственно сам метод. 
Немного непонятно, ОК, давайте расширим наш пример. 
Итак, добавим к коду две C#-функции, IvanSays и MikeSays:

public void IvanSays(string s)
{
Console.WriteLine("Ivan>" + s);
}
public void MikeSays(string s)
{
Console.WriteLine("Mike>" + s);
}   

Как видите, они не несут в себе ничего сложного, и просто выводят строку на экран консоли. 
Теперь переделаем нашу функцию Main, точнее, перепишем ее наново. Итак:

static void Main(string[] args)
{
Program program = new Program();
Lua lua = new Lua();
lua.RegisterFunction("Ivan", program, program.GetType().GetMethod("IvanSays"));
lua.RegisterFunction("Mike", program, program.GetType().GetMethod("MikeSays"));
lua.DoString("Ivan('Привет'); Mike('Привет, Иван!')");
Console.ReadLine();
}

Тут главное не запутаться, поэтому разъясним все подробно. Program — это базовый класс по умолчанию, в котором мы все делаем, теперь создаем его экземпляр, стартуем интерпретатор Lua, далее регистрируем Lua-функции с помощью RegisterFunction. Первую строку с перенаправлением следует читать так: метод IvanSays объекта program зарегистрирован как Lua-функция Ivan. Дальше в рамках использования метода DoString мы выполнили порции кода Lua, в рамках которых вызвали функции уже со своими именами и передали им параметры.  
Также обращаю внимание на то, что по синтаксису Lua оператор «;» как таковой является условным, то есть, его можно и не ставить в конце каждой исполняемой строки. 



С другой стороны, с его наличием код является более привычным для понимания у программистов С/С++/С#. В принципе, на Lua не очень часто пишут очень большие файлы — тут главное чтобы не получилось как с сокращением объемов «Войны и мира» Л. Н. Толстого после удаления из алфавита буквы «ять»:). 


DoFile


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

Итак, давайте создадим свой каталог для скриптов по адресу… …\LuaTest01\bin\Debug\, назовем его scripts. Такое место размещения выбрано для удобства, чтобы не вписывать потом в код абсолютные ссылки. И теперь создадим в папке scripts файл с диалогом, назвав его dialog.txt. Что в него поместим? Те же вызовы функций:

Ivan('Привет')
Mike('Привет, Иван!')
Ivan('Как дела?')
Mike('Тип-топ')
Теперь вместо DoString мы используем метод DoFile, который дает команду на исполнение указанного файла. И функция main у нас уже будет выглядеть следующим образом:
static void Main(string[] args)
{
Program program = new Program();
Lua lua = new Lua();
lua.RegisterFunction("Ivan", program, program.GetType().GetMethod("IvanSays"));
lua.RegisterFunction("Mike", program, program.GetType().GetMethod("MikeSays"));
lua.DoFile("scripts/dialog.txt");
Console.ReadLine();

Как вы можете увидеть, мы заменили всего одну строку, а сами команды по вызову функций исполняемого кода вынесли в отдельный файл. В данном случае продемонстрирован один из основных механизмов Lua, благодаря которому можно разделять блок основного кода от вспомогательного. 




Подытожим


Двигаться мы будем тематическими блоками и в следующей части начнем работать с классами. Нужно сказать, что многие разработчики часто избегают вставки скриптовых составляющих в свои проекты, на самом же деле это очень удобно. С другой стороны часть программистов/проектировщиков в целях улучшения переносимости (на другие языки и/или платформы) все, что только можно, переводят на скрипты. К последним относится и автор этих строк. Минусы у этого подхода также есть, потому как при неправильной расстановке приоритетов можно проиграть в производительности приложений. То есть всегда необходимо искать золотую середину.  


Кристофер

Перепечатка материалов или их фрагментов возможна только с согласия автора.





Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Ассоциация боевых роботов
Рекомендуем...
Новости

Разделы

Опросы

Какой язык программирования вы считаете наиболее актуальным сегодня?
Всего ответов: 308

Друзья

3D-кино






Найти на сайте:








Об авторе       Контакты      Вопрос-ответ        Хостинг от uCoz