2009-08-15 2 views
4

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

Я нашел некоторые библиотеки в сети, но так как мне нужно очень мало общей функциональности, которую они предоставляют, мне было интересно, есть ли простой способ сделать это.

спасибо.

+0

Какая проблема с lua_register у вас на самом деле? Является ли это видимостью функций, объявленных как звездные? –

ответ

4

API сложной библиотеки часто можно быстро и почти полностью обернуть, используя SWIG. Преимущество использования SWIG в этом случае заключается в том, что легко создавать оболочки SWIG, которые позволяют использовать библиотеку в 18 major languages, включая, среди прочих, Lua, Perl, Python, Ruby и Java.

Если Lua является вашей предпочтительной (и, возможно, единственной) проблемой, то я бы посоветовал научиться использовать luaL_register() в основе стратегии создания модулей Lua в C. Преимущество построения модуля таким образом заключается в том, что вы сохраняете все ваши функции в одном пространстве имен без каких-либо накладных расходов. Вам понадобится создать функцию-обертку, которая соответствует соглашению о вызове функции Lua C (как и в случае с lua_register()), и которая собирает аргументы Lua из стека, вызывает завернутую функцию и выталкивает любое возвращаемое значение и выводит параметры обратно в Стек Lua. Хороший обзор того, как это сделать, можно найти в книге «Программирование в Луа». Онлайн-копия первого издания обсуждает создание библиотеки в Chapter 26, но была написана для Lua 5.0. Я настоятельно призываю всех, кто серьезно использует Lua, иметь копию текущей версии PiL.

К сожалению, одна область, где Lua 5.1 отличается большей частью от 5.0, - это динамическая загрузка модулей (как C, так и Lua) с require.

Вот полный (если маленький) пример для библиотеки C, которая работает в Lua 5.1. Мы начнем с реализацией обертки в файле C:

#include <lua.h> 
#include <luaxlib.h> 
#include <math.h> 
#undef PI 
#define PI (3.14159265358979323846) 

static int l_sin (lua_State *L) { 
    double r = luaL_checknumber(L,1); 
    lua_pushnumber(L, sin(r)); 
    return 1; 
} 

static int l_cos (lua_State *L) { 
    double r = luaL_checknumber(L,1); 
    lua_pushnumber(L, cos(r)); 
    return 1; 
} 

static const struct luaL_reg smlib [] = { 
    {"sin", l_sin}, 
    {"cos", l_cos}, 
    {NULL, NULL} /* sentinel */ 
}; 

int luaopen_sm (lua_State *L) { 
    luaL_openlib(L, "sm", smlib, 0); 
    lua_pushnumber(L,PI); 
    lua_rawset(L,-2,"pi"); 
    return 1; 
} 

Примечания, в частности, что единственная функция, которая требуется на экспорте является luaopen_sm(), чье имя должны соответствовать имени модуля, который будет использоваться с require , а также имя файла DLL. С этим файлом скомпилированного как DLL с именем sm.dll (вероятно, назвали libsm.so на Unix-подобных системах), то он может быть загружен и использован в сценарии Lua так:

 
require "sm" 
print(sm.sin(sm.pi/3), sm.cos(sm.pi/3)); 

Этот пример, хотя тестировался, должен составить и запустить. Полный пример, охватывающий большинство функций от math.h, см. В source to the math module, который распространяется вместе с Lua. Поскольку эти тонкие обертки содержат много повторяющегося кода, такие инструменты, как SWIG, часто могут создавать их, учитывая только объявление каждой функции.

Способы упаковки класса C++ в принципе аналогичны. Каждой Lua-вызываемой функции-обертки понадобится аргумент, который может быть отображен на this на стороне C++, и он должен быть реализован либо как модуль-статическая функция, либо статическая функция-член, которая также находит экземпляр целевого объекта, а также преобразует другие аргументы. SWIG особенно хорош в создании такого рода обертки и скрыть много деталей gory на этом пути.

Смежные вопросы