2009-08-15 8 views
4

Je travaille actuellement sur l'implémentation de Lua dans l'une des applications sur lesquelles je travaille. Actuellement, j'utilise simplement les fonctions C api et d'enregistrement à l'aide de lua_register, mais j'aimerais pouvoir transmettre des pointeurs de fonction statiques et non statiques à certaines méthodes de classe.Lua scripting implementation

J'ai trouvé certaines bibliothèques sur le net, mais comme j'ai besoin de très peu de fonctionnalités globales, je me demandais s'il y avait un moyen facile de le faire.

Merci.

+0

Quel est le problème avec lua_register avez-vous réellement? Est-ce la visibilité des fonctions déclarées stariques? –

Répondre

4

Une bibliothèque API complexe peut souvent être enveloppée rapidement et (presque) complètement en utilisant SWIG. Un avantage de l'utilisation de SWIG dans ce cas est qu'il est facile de construire des wrappers basés sur SWIG qui permettent l'utilisation de la bibliothèque dans 18 major languages y compris Lua, Perl, Python, Ruby et Java, entre autres. Si Lua est votre préféré (et peut-être seulement), alors je vous recommande d'apprendre à utiliser luaL_register() au cœur d'une stratégie pour construire des modules Lua en C. Un avantage de construire un module de cette façon est que vous gardez toutes vos fonctions dans un espace de nom unique sans frais généraux. Vous devrez créer une fonction wrapper qui correspond à la convention d'appel de la fonction Lua C (comme avec lua_register()) et qui rassemble les arguments Lua de la pile, appelle la fonction encapsulée et repousse les valeurs de retour et les paramètres out vers le Pile Lua. Un bon aperçu de la façon de s'y prendre peut être trouvé dans le livre Programming in Lua. La copie en ligne de la première édition traite de la création de la bibliothèque au Chapter 26, mais a été écrite pour Lua 5.0. J'invite fortement quiconque à utiliser sérieusement Lua pour posséder une copie de l'édition actuelle de PiL.

Malheureusement, une zone où Lua 5.1 diffère le plus de 5.0 est dans le chargement dynamique des modules (C et Lua) avec require.

Voici un exemple complet (si petit) pour une bibliothèque C qui fonctionne dans Lua 5.1. Nous commençons par la mise en œuvre de l'enveloppe dans un fichier 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; 
} 

note en particulier que la seule fonction besoin d'être exportée est luaopen_sm(), dont le nom doit correspondre au nom du module qui sera utilisé avec require et avec le nom du fichier DLL. Avec ce fichier compilé comme une DLL nommée sm.dll (probablement nommé libsm.so sur les systèmes Unix), il peut être chargé et utilisé dans un script Lua comme ceci:

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

Cet exemple, bien que non testé, devrait compiler et courir. Pour un exemple complet enveloppant la plupart des fonctions de math.h, voir le source to the math module qui est distribué avec Lua. Parce que ces enveloppes minces contiennent beaucoup de code répétitif, des outils comme SWIG sont souvent en mesure de les créer avec seulement la déclaration de chaque fonction.

Les méthodes de wrapping d'une classe C++ sont similaires en principe. Chaque fonction wrapper appelable Lua va avoir besoin d'un argument qui peut être mappé en this du côté C++, et il doit être implémenté soit comme une fonction module-statique ou une fonction membre statique qui localise aussi l'instance d'objet cible ainsi que convertit les autres arguments. SWIG est particulièrement bon à la construction de ce type d'emballage et cache beaucoup de détails sanglants le long du chemin.