SWIG: Lua – передача экземпляра c ++ в качестве параметра функции lua

Я экспортирую некоторые classы c ++ в Lua с помощью SWIG. Я объявил boost :: fileystem :: path в файле интерфейса SWIG следующим образом:

namespace boost { namespace filesystem { class path {}; } } 

Теперь я хочу вызвать функцию, объявленную в сценарии lua, которая должна принять параметр boost :: filesystem :: path & as, чтобы передать его другому объекту. Мне нужно только пройти путь к объекту. Мне не нужно использовать какие-либо функции из объекта пути.

 function on_path_selected(the_path) another_object:set_path(the_path) end 

Я буду называть функцию Lua из c ++, используя ее индекс.

 lua_rawgeti(L, LUA_REGISTRYINDEX, m_function_index); lua_push[SOMETHING](L, path_object); // <-- HOW TO ? lua_pcall(L,1,0,0) 

ВОПРОС: Как подтолкнуть boost :: filesystem :: path как параметр к функции Lua?

Это на самом деле довольно сложно. Ожидаемое использование SWIG заключается в создании модhive для Lua. Сценарий Lua должен быть единственным, решающим, что называется, а что нет. Он не предназначен для встроенного использования, когда вы используете SWIG для отображения некоторых объектов C ++, а затем вызываете код Lua непосредственно из приложения.

Это не значит, что это невозможно, просто сложно.

Все объекты C ++ на основе SWIG передаются через Lua в качестве указателей. Таким образом, вопрос собственности – вопрос; вы не можете просто перетащить указатель на объект стека в Lua.

Самый безопасный способ сделать это – передать новую копию объекта в Lua. Таким образом, Lua владеет указателем. SWIG будет знать, что Lua владеет указателем и приложит к нему надлежащий механизм сбора мусора, чтобы очистить его. Так что все должно быть хорошо, память мудрая.

Но для этого требуется должным образом «бокс» (из-за отсутствия лучшего термина), которые возражают так, как это делает SWIG. Для этого требуется использование определенных макросов SWIG.

Учитывая, как вы связали тип path с SWIG, вы сделали бы что-то подобное, чтобы вставить его в стек Lua:

 swig_type_info *pathType = SWIG_TypeQuery("boost::filesystem::path *"); boost::filesystem::path *pArg = new boost::filesystem::path(the_path); SWIG_NewPointerObj(L, pArg, outputType, 1); 

SWIG_TypeQuery выбирает тип любого объекта, который был привязан SWIG к Lua. Этот информационный объект типа необходим для SWIG_NewPointerObj , который берет указатель на этот тип. Оба эти макроса. SWIG_NewPointerObj дает Lua право собственности на указатель; Сборщик мусора Lua удалит его благодаря метатегам SWIG. Кроме того, SWIG_NewPointerObj нажимает объект на стек lua_State .

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

Теперь, если вы введете этот код в свой проект, вероятность того, что вы получите ошибку компиляции, когда компилятор увидит swig_type_info . Этот тип определяется внутри исходного файла, сгенерированного в командной строке SWIG.

У вас есть два варианта:

  1. Поместите этот исходный код в сам файл .swig. Да, действительно. Вы можете определить регулярные функции C ++ там, внутри разделов стенограммы (блоки, ограниченные %{ %} ). Эти функции будут скопированы непосредственно в сгенерированный код SWIG. Вы можете получить к ним доступ, поставив прототипы в заголовки. Это самый простой и простой способ работы. Это часто используется для создания специальных интерфейсов, где ранее существовавшая функция C ++ не подходит для Lua API (или просто не существует).

  2. Вы можете создать соответствующий заголовок, содержащий эти определения, с аргументом -external-runtime . Это должен быть другой шаг выполнения SWIG с шага, который генерирует .cpp-файл. Смотрите, он фактически не обрабатывает файл SWIG или что-то еще. Все, что ему нужно, это целевой язык ( -lua ) и используете ли вы C ++ ( -c++ ). У вас просто есть команда, которая выполняет swig -c++ -lua -external-runtime someheader.h , и это все, что вам нужно получить типы и macros.

    Включите этот заголовок в любой источник, который вы хотите подключить к объектам, связанным с SWIG, к Lua in.