Skip to content

Commit 3ee31ab

Browse files
committed
Add lua_CFunction registration support
1 parent 18983c8 commit 3ee31ab

File tree

2 files changed

+136
-29
lines changed

2 files changed

+136
-29
lines changed

Demo/Source/NewTests.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,23 @@ struct C
8484
{
8585
v = v_;
8686
}
87+
88+
static int static_cfunc (lua_State*)
89+
{
90+
return 0;
91+
}
92+
93+
int cfunc (lua_State*)
94+
{
95+
return 0;
96+
}
8797
};
8898

99+
int cfunc (lua_State*)
100+
{
101+
return 0;
102+
}
103+
89104
void byptr (A*)
90105
{
91106
}
@@ -113,7 +128,10 @@ void addToState (lua_State* L) {
113128
.endClass ()
114129
.beginClass <C> ("C")
115130
.addProperty ("v", &C::get, &C::set)
131+
.addStaticCFunction ("static_cfunc", &C::static_cfunc)
132+
.addCFunction ("cfunc", &C::cfunc)
116133
.endClass ()
134+
.addCFunction ("cfunc", &cfunc)
117135
.addFunction ("byptr", &byptr)
118136
.addFunction ("byref", &byref)
119137
.endNamespace ();

LuaBridge/LuaBridge.h

Lines changed: 118 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -128,13 +128,17 @@
128128
129129
## Registration
130130
131-
There are four types of objects that LuaBridge can register:
131+
There are five types of objects that LuaBridge can register:
132132
133133
- **Data**: Global variables, static class data members, and class data
134134
members.
135135
136136
- **Functions**: Regular functions, static class members, and class member
137-
functions
137+
functions.
138+
139+
- **CFunctions**: A regular function, static class member function, or class
140+
member function that uses the `lua_CFunction` calling
141+
convention.
138142
139143
- **Namespaces**: A namespace is simply a table containing registrations of
140144
functions, data, properties, and other namespaces.
@@ -185,16 +189,15 @@
185189
186190
The results are accessible to Lua as `test`, `test.detail`, and
187191
`test.utility`. Here we introduce the `endNamespace` function; it returns an
188-
object representing the original enclosing namespace. All LuaBridge functions which
189-
create registrations return an object upon which subsequent registrations can
190-
be made, allowing for an unlimited number of registrations to be chained
191-
together using the dot operator `.`. Adding two objects with the same name, in
192-
the same namespace, results in undefined behavior (although LuaBridge will
193-
silently accept it).
192+
object representing the original enclosing namespace. All LuaBridge functions
193+
which create registrations return an object upon which subsequent
194+
registrations can be made, allowing for an unlimited number of registrations
195+
to be chained together using the dot operator `.`. Adding two objects with the
196+
same name, in the same namespace, results in undefined behavior (although
197+
LuaBridge will silently accept it).
194198
195-
A namespace can be re-opened later to add
196-
more functions. This lets you split up the registration between different
197-
source files. These are equivalent:
199+
A namespace can be re-opened later to add more functions. This lets you split
200+
up the registration between different source files. These are equivalent:
198201
199202
getGlobalNamespace (L)
200203
.beginNamespace ("test")
@@ -215,15 +218,16 @@
215218
.endNamespace ();
216219
217220
218-
### Data, Properties, and Functions
221+
### Data, Properties, Functions, and CFunctions.
219222
220223
These are registered into a namespace using `addVariable`, `addProperty`,
221-
and `addFunction`. When registered functions are called by scripts, LuaBridge
222-
automatically takes care of the conversion of arguments into the appropriate
223-
data type when doing so is possible. This automated system works for the
224-
function's return value, and up to 8 parameters although more can be added by
225-
extending the templates. Pointers, references, and objects of class type as
226-
parameters are treated specially, and explained later. If we have:
224+
`addFunction`, and `addCFunction`. When registered functions are called by
225+
scripts, LuaBridge automatically takes care of the conversion of arguments
226+
into the appropriate data type when doing so is possible. This automated
227+
system works for the function's return value, and up to 8 parameters although
228+
more can be added by extending the templates. Pointers, references, and
229+
objects of class type as parameters are treated specially, and explained
230+
later. If we have:
227231
228232
int globalVar;
229233
static float staticVar;
@@ -234,8 +238,9 @@
234238
235239
int foo () { return 42; }
236240
void bar (char const*) { }
241+
int cFunc (lua_State* L) { return 0; }
237242
238-
These are registered with:
243+
These are registered with:
239244
240245
getGlobalNamespace (L)
241246
.beginNamespace ("test")
@@ -245,6 +250,7 @@
245250
.addProperty ("prop2", getString) // read only
246251
.addFunction ("foo", foo)
247252
.addFunction ("bar", bar)
253+
.addCFunction ("cfunc", cFunc)
248254
.endNamespace ();
249255
250256
Variables can be marked _read-only_ by passing `false` in the second optional
@@ -259,6 +265,7 @@
259265
test.prop2 -- a read-only lua_String property
260266
test.foo -- a function returning a lua_Number
261267
test.bar -- a function taking a lua_String as a parameter
268+
test.cfunc -- a function with a variable argument list and multi-return
262269
263270
Note that `test.prop1` and `test.prop2` both refer to the same value. However,
264271
since `test.prop2` is read-only, assignment does not work. These Lua
@@ -297,6 +304,8 @@
297304
static void setStaticProperty (float f) { staticProperty = f; }
298305
static void staticFunc () { }
299306
307+
static int staticCFunc () { return 0; }
308+
300309
std::string dataMember;
301310
302311
char dataProperty;
@@ -305,6 +314,8 @@
305314
306315
void func1 () { }
307316
virtual void virtualFunc () { }
317+
318+
int cfunc (lua_State* L) { return 0; }
308319
};
309320
310321
struct B : public A {
@@ -326,10 +337,12 @@
326337
.addStaticData ("staticData", &A::staticData)
327338
.addStaticProperty ("staticProperty", &A::staticProperty)
328339
.addStaticMethod ("staticFunc", &A::staticFunc)
340+
.addStaticCFunction ("staticCFunc", &A::staticCFunc)
329341
.addData ("data", &A::dataMember)
330342
.addProperty ("prop", &A::getProperty, &A::setProperty)
331343
.addMethod ("func1", &A::func1)
332344
.addMethod ("virtualFunc", &A::virtualFunc)
345+
.addCFunction ("cfunc", &A::cfunc)
333346
.endClass ()
334347
.deriveClass <B, A> ("B")
335348
.addData ("data", &B::dataMember2)
@@ -3440,7 +3453,7 @@ class Namespace
34403453
*/
34413454
template <class MemFn,
34423455
class ReturnType = typename FuncTraits <MemFn>::ReturnType>
3443-
struct CallMember
3456+
struct CallMemberFunction
34443457
{
34453458
typedef typename FuncTraits <MemFn>::ClassType T;
34463459
typedef typename FuncTraits <MemFn>::Params Params;
@@ -3471,7 +3484,7 @@ class Namespace
34713484
lua_CFunction to call a class member function with no return value.
34723485
*/
34733486
template <class MemFn>
3474-
struct CallMember <MemFn, void>
3487+
struct CallMemberFunction <MemFn, void>
34753488
{
34763489
typedef typename FuncTraits <MemFn>::ClassType T;
34773490
typedef typename FuncTraits <MemFn>::Params Params;
@@ -3495,30 +3508,54 @@ class Namespace
34953508
}
34963509
};
34973510

3511+
//----------------------------------------------------------------------------
3512+
/**
3513+
lua_CFunction to call a class member lua_CFunction
3514+
*/
3515+
template <class T>
3516+
struct CallMemberCFunction
3517+
{
3518+
static int call (lua_State* L)
3519+
{
3520+
typedef int (T::*MFP)(lua_State* L);
3521+
T* const t = Detail::Userdata::get <T> (L, 1, false);
3522+
MFP const mfp = *static_cast <MFP*> (lua_touserdata (L, lua_upvalueindex (1)));
3523+
return (t->*mfp) (L);
3524+
}
3525+
3526+
static int callConst (lua_State* L)
3527+
{
3528+
typedef int (T::*MFP)(lua_State* L);
3529+
T const* const t = Detail::Userdata::get <T> (L, 1, true);
3530+
MFP const mfp = *static_cast <MFP*> (lua_touserdata (L, lua_upvalueindex (1)));
3531+
return (t->*mfp) (L);
3532+
}
3533+
};
3534+
34983535
//----------------------------------------------------------------------------
34993536

35003537
// SFINAE Helpers
35013538

35023539
template <class MemFn, bool isConst>
3503-
struct CallMemberHelper
3540+
struct CallMemberFunctionHelper
35043541
{
35053542
static void add (lua_State* L, char const* name, MemFn mf)
35063543
{
35073544
new (lua_newuserdata (L, sizeof (MemFn))) MemFn (mf);
3508-
lua_pushcclosure (L, &CallMember <MemFn>::callConst, 1);
3545+
lua_pushcclosure (L, &CallMemberFunction <MemFn>::callConst, 1);
35093546
lua_pushvalue (L, -1);
35103547
rawsetfield (L, -5, name); // const table
35113548
rawsetfield (L, -3, name); // class table
35123549
}
35133550
};
35143551

35153552
template <class MemFn>
3516-
struct CallMemberHelper <MemFn, false>
3553+
struct CallMemberFunctionHelper <MemFn, false>
35173554
{
35183555
static void add (lua_State* L, char const* name, MemFn mf)
35193556
{
35203557
new (lua_newuserdata (L, sizeof (MemFn))) MemFn (mf);
3521-
lua_pushcclosure (L, &CallMember <MemFn>::call, 1);
3558+
lua_pushcclosure (L, &CallMemberFunction <MemFn>::call, 1);
35223559
rawsetfield (L, -3, name); // class table
35233560
}
35243561
};
@@ -4100,6 +4137,17 @@ class Namespace
41004137
return *this;
41014138
}
41024139

4140+
//--------------------------------------------------------------------------
4141+
/**
4142+
Add or replace a lua_CFunction.
4143+
*/
4144+
Class <T>& addStaticCFunction (char const* name, int (*const fp)(lua_State*))
4145+
{
4146+
lua_pushcfunction (L, fp);
4147+
rawsetfield (L, -2, name);
4148+
return *this;
4149+
}
4150+
41034151
//--------------------------------------------------------------------------
41044152
/**
41054153
Add or replace a data member.
@@ -4148,7 +4196,7 @@ class Namespace
41484196
rawgetfield (L, -4, "__propget");
41494197
typedef GT (T::*get_t) () const;
41504198
new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
4151-
lua_pushcclosure (L, &CallMember <get_t>::callConst, 1);
4199+
lua_pushcclosure (L, &CallMemberFunction <get_t>::callConst, 1);
41524200
lua_pushvalue (L, -1);
41534201
rawsetfield (L, -4, name);
41544202
rawsetfield (L, -2, name);
@@ -4161,7 +4209,7 @@ class Namespace
41614209
assert (lua_istable (L, -1));
41624210
typedef void (T::* set_t) (ST);
41634211
new (lua_newuserdata (L, sizeof (set_t))) set_t (set);
4164-
lua_pushcclosure (L, &CallMember <set_t>::call, 1);
4212+
lua_pushcclosure (L, &CallMemberFunction <set_t>::call, 1);
41654213
rawsetfield (L, -2, name);
41664214
lua_pop (L, 1);
41674215
}
@@ -4178,7 +4226,7 @@ class Namespace
41784226
rawgetfield (L, -4, "__propget");
41794227
typedef GT (T::*get_t) () const;
41804228
new (lua_newuserdata (L, sizeof (get_t))) get_t (get);
4181-
lua_pushcclosure (L, &CallMember <get_t>::callConst, 1);
4229+
lua_pushcclosure (L, &CallMemberFunction <get_t>::callConst, 1);
41824230
lua_pushvalue (L, -1);
41834231
rawsetfield (L, -4, name);
41844232
rawsetfield (L, -2, name);
@@ -4254,7 +4302,37 @@ class Namespace
42544302
template <class MemFn>
42554303
Class <T>& addMethod (char const* name, MemFn mf)
42564304
{
4257-
CallMemberHelper <MemFn, FuncTraits <MemFn>::isConstMemberFunction>::add (L, name, mf);
4305+
CallMemberFunctionHelper <MemFn, FuncTraits <MemFn>::isConstMemberFunction>::add (L, name, mf);
4306+
return *this;
4307+
}
4308+
4309+
//--------------------------------------------------------------------------
4310+
/**
4311+
Add or replace a member lua_CFunction.
4312+
*/
4313+
Class <T>& addCFunction (char const* name, int (T::*mfp)(lua_State*))
4314+
{
4315+
typedef int (T::*MFP)(lua_State*);
4316+
assert (lua_istable (L, -1));
4317+
new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp);
4318+
lua_pushcclosure (L, &CallMemberCFunction <T>::call, 1);
4319+
rawsetfield (L, -2, name);
4320+
4321+
return *this;
4322+
}
4323+
4324+
//--------------------------------------------------------------------------
4325+
/**
4326+
Add or replace a const member lua_CFunction.
4327+
*/
4328+
Class <T>& addCFunction (char const* name, int (T::*mfp)(lua_State*) const)
4329+
{
4330+
typedef int (T::*MFP)(lua_State*) const;
4331+
assert (lua_istable (L, -1));
4332+
new (lua_newuserdata (L, sizeof (mfp))) MFP (mfp);
4333+
lua_pushcclosure (L, &CallMemberCFunction <T>::callConst, 1);
4334+
rawsetfield (L, -2, name);
4335+
42584336
return *this;
42594337
}
42604338

@@ -4519,6 +4597,17 @@ class Namespace
45194597
return *this;
45204598
}
45214599

4600+
//----------------------------------------------------------------------------
4601+
/**
4602+
Add or replace a lua_CFunction.
4603+
*/
4604+
Namespace& addCFunction (char const* name, int (*const fp)(lua_State*))
4605+
{
4606+
lua_pushcfunction (L, fp);
4607+
rawsetfield (L, -2, name);
4608+
return *this;
4609+
}
4610+
45224611
//----------------------------------------------------------------------------
45234612
/**
45244613
Open a new or existing class for registrations.

0 commit comments

Comments
 (0)