1 module luad.lmodule;
2 
3 import luad.state;
4 import luad.stack;
5 import luad.conversions.functions;
6 
7 import luad.c.lua : lua_State;
8 
9 import std.traits;
10 
11 // Internal, but needs to be public
12 extern(C) int openDModule(F)(lua_State* L, F initFunc)
13 {
14 	auto lua = new LuaState(L);
15 
16 	alias ParameterTypeTuple!F Args;
17 
18 	static assert(Args.length > 0 && Args.length < 3 &&
19 				  is(Args[0] == LuaState),
20 				  "invalid initFunc signature");
21 
22 	Args args;
23 	args[0] = lua;
24 
25 	static if(Args.length == 2)
26 	{
27 		static assert(is(Args[1] : const(char[])), "second parameter to initFunc must be a const string");
28 		args[1] = getArgument!(F, 1)(L, -1);
29 	}
30 
31 	return callFunction!F(L, initFunc, args);
32 }
33 
34 /**
35  * Generate module entry point for use by Lua's $(D require) function.
36  *
37  * Params:
38  *   modname = module name. Typically this should be the same as the name of
39  *   the shared library containing this module. Only characters in the set
40  *   $(D [a-zA-Z_]) are allowed. Underscores are used to denote a submodule.
41  *   The module name must be unique for the current executable.
42  *
43  *   initFunc = module initialization function. Called when the module is loaded.
44  *   Its return value is returned by $(D require) on the Lua side. Its first
45  *   parameter must be of type $(DPREF state,LuaState), which is the state of the calling environment.
46  *   Optionally, there may be a second parameter implicitly convertible to the type
47  *   $(D const(char[])), which is the name of the module to be loaded (useful for submodules).
48  */
49 // TODO: verify modname
50 template LuaModule(string modname, alias initFunc)
51 {
52 	enum LuaModule = "import luad.c.lua : lua_State;" ~
53 		// The first exported C symbol always gets a preceeding
54 		// underscore on Windows with DMD/OPTLINK, but Lua
55 		// expects "luaopen_*" exactly.
56 		"version(Windows) export extern(C) void _luad_" ~ modname ~ "_systemconvdummy() {}" ~
57 		"export extern(C) int luaopen_" ~ modname ~ "(lua_State* L) {" ~
58 			  "return openDModule(L, &" ~ __traits(identifier, initFunc) ~ ");" ~
59 		"}";
60 }