Eine komplexe Bibliothek API kann oft schnell und (fast) vollständig mit SWIG gewickelt werden. Ein Vorteil der Verwendung von SWIG in diesem Fall besteht darin, dass es einfach ist, SWIG-basierte Wrapper zu erstellen, die die Verwendung der Bibliothek in 18 major languages einschließlich Lua, Perl, Python, Ruby und Java unter anderem ermöglichen.
Wenn Lua ist Ihre bevorzugte (und möglicherweise nur) Anliegen, dann würde ich empfehlen zu lernen, im Kern einer Strategie zu verwenden, um Lua-Module in C zu bauen. Ein Vorteil des Aufbaus eines Moduls auf diese Weise ist, dass Sie behalten alle Ihre Funktionen in einem einzigen Namespace ohne Overhead. Sie müssen eine Wrapper-Funktion erstellen, die der Aufrufkonvention der Lua C-Funktion entspricht (genau wie bei lua_register()
) und die Lua-Argumente vom Stapel sammelt, die Wrapped-Funktion aufruft und alle Rückgabewert- und Ausgabeparameter zurück an die Lua-Stapel. Einen guten Überblick darüber gibt das Buch Programming in Lua. Die Online-Kopie der ersten Edition beschreibt Bibliothekserstellung in Chapter 26, wurde aber für Lua 5.0 geschrieben. Ich fordere jeden dringend auf, Lua ernsthaft zu benutzen, um eine Kopie der aktuellen Ausgabe von PiL zu besitzen.
Leider unterscheidet sich ein Bereich, in dem sich Lua 5.1 am meisten von 5.0 unterscheidet, in der dynamischen Belastung von Modulen (C und Lua) mit require
.
Hier ist ein vollständiges (falls klein) Beispiel für eine C-Bibliothek, die in Lua 5.1 funktioniert. Wir beginnen mit der Umsetzung der Umhüllung in einer C-Datei:
#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;
}
Hinweis insbesondere, dass die einzige Funktion, die luaopen_sm()
ist exportiert werden muss, dessen Name mit dem Namen des Moduls entspricht, die mit require
verwendet werden und mit dem Namen der DLL-Datei. Mit dieser Datei als DLL kompiliert sm.dll
genannt (wahrscheinlich libsm.so
auf Unix-ähnlichen Systemen genannt), dann kann es in einem Lua Skript wie folgt geladen und verwendet werden:
require "sm"
print(sm.sin(sm.pi/3), sm.cos(sm.pi/3));
, obwohl nicht getestet Dieses Beispiel sollte kompilieren und Lauf. Für ein vollständiges Beispiel, das die meisten Funktionen von math.h
umschließt, siehe source to the math
module, das mit Lua vertrieben wird. Da diese dünnen Wrapper viel repetitiven Code enthalten, können Tools wie SWIG sie oft nur mit der Deklaration jeder Funktion erstellen.
Wrapping Methoden einer C++ Klasse ist im Prinzip ähnlich. Jede von Lua aufrufbare Wrapper-Funktion benötigt ein Argument, das auf C++ - Seite in this
abgebildet werden kann, und es muss entweder als eine Modul-statische Funktion oder eine statische Elementfunktion implementiert werden, die die Zielobjektinstanz sowie Konvertierungen lokalisiert die anderen Argumente. SWIG ist besonders gut in der Konstruktion dieser Art von Wrapper und versteckt viele blutige Details auf dem Weg.
Welches Problem mit lua_register haben Sie eigentlich? Ist es die Sichtbarkeit von Funktionen, die als starr erklärt wurden? –