Browse Source

3rd pass on lua classes. It works now. It's ..... ALIIIIIIVE

undefined
Benjamin ‘Touky’ Huet Sam Hocevar <sam@hocevar.net> 10 years ago
parent
commit
cf888d721d
9 changed files with 966 additions and 127 deletions
  1. +14
    -1
      build/Lol (vs2013).sln
  2. +290
    -0
      doc/tutorial/14_lol_lua.cpp
  3. +16
    -0
      doc/tutorial/14_lol_lua.lua
  4. +76
    -0
      doc/tutorial/14_lol_lua.vcxproj
  5. +5
    -1
      doc/tutorial/Makefile.am
  6. +14
    -9
      src/application/baselua.cpp
  7. +549
    -61
      src/application/baselua.h
  8. +1
    -14
      src/world.cpp
  9. +1
    -41
      src/world.h

+ 14
- 1
build/Lol (vs2013).sln View File

@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
VisualStudioVersion = 12.0.21005.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "deushax", "..\games\deushax\deushax.vcxproj", "{EF1A4E80-63FA-4EB0-B834-12B6C500F31C}"
EndProject
@@ -153,6 +153,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Doc", "Doc", "{65FD48E9-C93
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shared", "..\people\touky\shared\shared.vcxproj", "{EE203B88-44CF-4859-9D42-7A4F43FEDB52}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "14_lol_lua", "..\doc\tutorial\14_lol_lua.vcxproj", "{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ORBIS = Debug|ORBIS
@@ -626,6 +628,16 @@ Global
{EE203B88-44CF-4859-9D42-7A4F43FEDB52}.Release|Win32.Build.0 = Release|Win32
{EE203B88-44CF-4859-9D42-7A4F43FEDB52}.Release|x64.ActiveCfg = Release|x64
{EE203B88-44CF-4859-9D42-7A4F43FEDB52}.Release|x64.Build.0 = Release|x64
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Debug|ORBIS.ActiveCfg = Debug|Win32
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Debug|Win32.ActiveCfg = Debug|Win32
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Debug|Win32.Build.0 = Debug|Win32
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Debug|x64.ActiveCfg = Debug|x64
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Debug|x64.Build.0 = Debug|x64
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Release|ORBIS.ActiveCfg = Release|Win32
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Release|Win32.ActiveCfg = Release|Win32
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Release|Win32.Build.0 = Release|Win32
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Release|x64.ActiveCfg = Release|x64
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -667,6 +679,7 @@ Global
{572E5B9C-7E19-489C-BD8A-E8401CFBBC47} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04}
{E05E23A5-67DE-42B5-98A3-E63CCE0CC0AF} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04}
{F59FA82C-DDB9-4EE2-80AE-CB0E4C6567A4} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04}
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04}
{32F3F8CF-D22E-45E4-BEB8-AD909E8C5515} = {33704AA4-F2B5-4138-A40D-E3E77F89ED46}
{EE203B88-44CF-4859-9D42-7A5F40FECB52} = {8C77EAA8-1077-4EF7-AE53-97C6C60A3601}
{B357514A-7881-422D-8358-161B689E7620} = {3D341D8A-E400-4B1D-BC05-B5C35487D9B5}


+ 290
- 0
doc/tutorial/14_lol_lua.cpp View File

@@ -0,0 +1,290 @@
//
// Lol Engine - Graphing tutorial
//
// Copyright: (c) 2012-2013 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
//

#if HAVE_CONFIG_H
# include "config.h"
#endif

#include <lol/engine.h>
#include "loldebug.h"
#include <cstdio>

using namespace lol;

//-----------------------------------------------------------------------------
class FooTest
{
public:
FooTest()
{
}
static int New(Lolua::State* l)
{
int n_args = lua_gettop(l); // Number of arguments

// We could actually allocate Foo itself as a user data but
// since user data can be GC'ed and we gain unity by using CRT's heap
// all along.
FooTest** udata = (FooTest**)lua_newuserdata(l, sizeof(FooTest*));
*udata = new FooTest();

// Usually, we'll just use "Foo" as the second parameter, but I
// say luaL_Foo here to distinguish the difference:
//
// This 2nd parameter here is an _internal label_ for luaL, it is
// _not_ exposed to Lua by default.
//
// Effectively, this metatable is not accessible by Lua by default.
//luaL_getmetatable(l, m_table_name);

// The Lua stack at this point looks like this:
//
// 3| metatable "luaL_foo" |-1
// 2| userdata |-2
// 1| string parameter |-3
//
// So the following line sets the metatable for the user data to the luaL_Foo
// metatable
//
// We must set the metatable here because Lua prohibits setting
// the metatable of a userdata in Lua. The only way to set a metatable
// of a userdata is to do it in C.
//lua_setmetatable(l, -2);

luaL_getmetatable(l, m_table2_name);
lua_setmetatable(l, -2);

// The Lua stack at this point looks like this:
//
// 2| userdata |-1
// 1| string parameter |-2
//
// We return 1 so Lua callsite will get the user data and
// Lua will clean the stack after that.

return 1;
}
static FooTest* Check(Lolua::State* l, int n)
{
// This checks that the argument is a userdata
// with the metatable "luaL_Foo"
return *(FooTest**)luaL_testudata(l, n, m_table2_name);
}
static int Del(Lolua::State * l)
{
FooTest* foo = Check(l, 1);
delete foo;

return 0;
}
static void Register(Lolua::State * l)
{
// Create a luaL metatable. This metatable is not
// exposed to Lua. The "luaL_Foo" label is used by luaL
// internally to identity things.
luaL_newmetatable(l, m_table2_name);
luaL_setfuncs(l, FooTest::m_statics2, 0);
lua_pushvalue(l, -1);
lua_setfield(l, -1, "__index");
//lua_setglobal(l, m_class2_name);
lua_pop(l, 1);

// Create a luaL metatable. This metatable is not
// exposed to Lua. The "luaL_Foo" label is used by luaL
// internally to identity things.
luaL_newmetatable(l, m_table_name);

// Register the C functions _into_ the metatable we just created.
luaL_setfuncs(l, FooTest::m_statics, 0);

// The Lua stack at this point looks like this:
//
// 1| metatable "luaL_Foo" |-1
lua_pushvalue(l, -1);

// The Lua stack at this point looks like this:
//
// 2| metatable "luaL_Foo" |-1
// 1| metatable "luaL_Foo" |-2

// Set the "__index" field of the metatable to point to itself
// This pops the stack
lua_setfield(l, -1, "__index");

// The Lua stack at this point looks like this:
//
// 1| metatable "luaL_Foo" |-1

// The luaL_Foo metatable now has the following fields
// - __gc
// - __index
// - new

// Now we use setglobal to officially expose the luaL_Foo metatable
// to Lua. And we use the name "Foo".
//
// This allows Lua scripts to _override_ the metatable of Foo.
// For high security code this may not be called for but
// we'll do this to get greater flexibility.
lua_setglobal(l, m_class_name);
}
static int Test1(Lolua::State* L)
{
Lolua::Var<int> i1(L, 1);
i1 += 5;
return i1.Return(L);
}
static int Test2(Lolua::State* L)
{
FooTest* foo = Check(L, 1);
Lolua::Var<float> i1(L, 2);
i1 = foo->Test2Inst(i1.V());
return i1.Return(L);
}
float Test2Inst(float f)
{
return (f + 10);
}

static const char m_class_name[];
static const char m_class2_name[];
static const char m_table_name[];
static const char m_table2_name[];
static const luaL_Reg m_statics[];
static const luaL_Reg m_statics2[];
static const luaL_Reg m_methods[];
};

const luaL_Reg FooTest::m_statics[] = {
{ "New", &FooTest::New },
{ "__gc", &FooTest::Del },
{ "Test1", &FooTest::Test1 },
{ NULL, NULL } };
const luaL_Reg FooTest::m_statics2[] = {
{ "Test2", &FooTest::Test2 },
{ NULL, NULL } };
const luaL_Reg FooTest::m_methods[] = { { NULL, NULL } };
const char FooTest::m_class_name[] = "FooTest";
const char FooTest::m_class2_name[] = "FooTest2";
const char FooTest::m_table_name[] = "FooTest_mt";
const char FooTest::m_table2_name[] = "FooTest_mt2";

typedef Lolua::ObjectDef<FooTest> FooTestLuaBase;
class FooTestLua : public FooTestLuaBase
{
public:
FooTestLua() : FooTestLuaBase() {}
virtual ~FooTestLua() {}
static FooTestLua* New(Lolua::State* l, int arg_nb)
{
return new FooTestLua();
}
static const char* GetClassName();
static const char* GetClassLibName();
static const char* GetClassInstName();
static const Lolua::ClassMethod* GetStaticMethods();
static const Lolua::ClassMethod* GetInstanceMethods();
static int Test1(Lolua::State* L)
{
Lolua::Var<int> i1(L, 1);
i1 += 5;
return i1.Return(L);
}
static int Test2(Lolua::State* L)
{
Lolua::VarPtr<FooTestLua> foo(L, 1);
Lolua::Var<float> i1(L, 2);
i1 = foo.V()->Test2Inst(i1.V());
return i1.Return(L);
}
float Test2Inst(float f)
{
return (f + 10);
}
};

static const Lolua::ClassMethod FooTest_statics[] = { { "Test1", &FooTestLua::Test1 }, { NULL, NULL } };
const Lolua::ClassMethod FooTest_methods[] = { { "Test2", &FooTestLua::Test2 }, { NULL, NULL } };

const char* FooTestLua::GetClassName() { static const char name[] = "FooTest"; return name; }
const char* FooTestLua::GetClassLibName() { static const char name[] = "FooTestLib"; return name; }
const char* FooTestLua::GetClassInstName() { static const char name[] = "FooTestInst"; return name; }
const Lolua::ClassMethod* FooTestLua::GetStaticMethods() { return FooTest_statics; }
const Lolua::ClassMethod* FooTestLua::GetInstanceMethods() { return FooTest_methods; }

//-----------------------------------------------------------------------------
class LoluaDemoLoader : public Lolua::Loader
{
public:
LoluaDemoLoader() : Lolua::Loader()
{
Lolua::State* l = GetLuaState();

Lolua::Object::Register<FooTestLua>(l);

ExecLua("14_lol_lua.lua");
}
virtual ~LoluaDemoLoader()
{

}
};

//-----------------------------------------------------------------------------
class LoluaDemo : public WorldEntity
{
public:
LoluaDemo()
{
}

virtual void TickGame(float seconds)
{
WorldEntity::TickGame(seconds);

LoluaDemoLoader* demo_loader = new LoluaDemoLoader();

float TestValueNum = demo_loader->GetVar<float>("TestValueNum");
int32_t TestValueInt = demo_loader->GetVar<int32_t>("TestValueInt");
uint32_t TestValueUint = demo_loader->GetVar<uint32_t>("TestValueUint");
String TestValueStr = demo_loader->GetVar<String>("TestValueStr");
//String test_return2 = demo_loader->GetVar<String>("test_return2");
//String test_return3 = demo_loader->GetVar<String>("test_return3");
int32_t testtruc_return = demo_loader->GetVar<int32_t>("footest_return");
float testtruc_return2 = demo_loader->GetVar<float>("footest_return2");
//int32_t testtruc2_return = demo_loader->GetVar<int32_t>("testtruc_return2");

String::Printf("Lua Vars: TestValueNum: %.2f, TestValueInt: %i, TestValueUint: %i, TestValueStr: %s.",
TestValueNum, TestValueInt, TestValueUint, TestValueStr);

delete demo_loader;

Ticker::Shutdown();
}

virtual void TickDraw(float seconds, Scene &scene)
{
WorldEntity::TickDraw(seconds, scene);
}
};

//-----------------------------------------------------------------------------
int main(int argc, char **argv)
{
System::Init(argc, argv);

Application app("Tutorial 14: Lolua Demo", ivec2(800, 600), 60.0f);

new LoluaDemo();

app.Run();
return EXIT_SUCCESS;
}


+ 16
- 0
doc/tutorial/14_lol_lua.lua View File

@@ -0,0 +1,16 @@
-- Number
TestValueNum = 900.0
-- Integer
TestValueInt = -900
-- Unsigned
TestValueUint = 900
-- String
TestValueStr = "900"

footest_return = FooTest.Test1(1);
footest_inst = FooTest.New(1,2);
footest_return2 = footest_inst:Test2(2.0);
-- test_return3 = sTest2("bruttruc");
-- testtruc_return2 = Testtruc.Test2(2);
-- test_return2 = Testtruc:Test2("brut");
-- test_return = LoluaTestObj:getTest(1, "brut");

+ 76
- 0
doc/tutorial/14_lol_lua.vcxproj View File

@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ORBIS">
<Configuration>Debug</Configuration>
<Platform>ORBIS</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Xbox 360">
<Configuration>Debug</Configuration>
<Platform>Xbox 360</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ORBIS">
<Configuration>Release</Configuration>
<Platform>ORBIS</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Xbox 360">
<Configuration>Release</Configuration>
<Platform>Xbox 360</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(SolutionDir)\..\src\lolcore.vcxproj">
<Project>{9e62f2fe-3408-4eae-8238-fd84238ceeda}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\src\bullet\lolbullet.vcxproj">
<Project>{83d3b207-c601-4025-8f41-01dedc354661}</Project>
</ProjectReference>
<ProjectReference Include="$(SolutionDir)\..\src\lua\lollua.vcxproj">
<Project>{d84021ca-b233-4e0f-8a52-071b83bbccc4}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClCompile Include="14_lol_lua.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="14_lol_lua.lua">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</None>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}</ProjectGuid>
<ConfigurationType>Application</ConfigurationType>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(SolutionDir)\msbuild\lol.config.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(SolutionDir)\msbuild\lolfx.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(SolutionDir)\msbuild\lol.vars.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<Import Project="$(SolutionDir)\msbuild\lol.rules.props" />
<ItemDefinitionGroup />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(SolutionDir)\msbuild\lolfx.targets" />
</ImportGroup>
</Project>

+ 5
- 1
doc/tutorial/Makefile.am View File

@@ -3,7 +3,7 @@ include $(top_srcdir)/build/autotools/common.am

noinst_PROGRAMS = 01_triangle 02_cube 03_noise 04_texture 05_easymesh \
06_sprite 07_input 08_fbo 11_fractal \
12_voronoi 13_shader_builder
12_voronoi 13_shader_builder 14_lol_lua

01_triangle_SOURCES = 01_triangle.cpp 01_triangle.lolfx
01_triangle_CPPFLAGS = $(AM_CPPFLAGS)
@@ -55,3 +55,7 @@ endif
13_shader_builder_CPPFLAGS = $(AM_CPPFLAGS)
13_shader_builder_DEPENDENCIES = @LOL_DEPS@

14_lol_lua_SOURCES = 14_lol_lua.cpp
14_lol_lua_CPPFLAGS = $(AM_CPPFLAGS)
14_lol_lua_DEPENDENCIES = @LOL_DEPS@


+ 14
- 9
src/application/baselua.cpp View File

@@ -23,9 +23,9 @@ namespace lol
//-----------------------------------------------------------------------------
class LuaBaseData
{
friend class LuaLoader;
friend class Lolua::Loader;

static int LuaPanic(lua_State* L)
static int LuaPanic(Lolua::State* L)
{
char const *message = lua_tostring(L, -1);
Log::Error("%s\n", message);
@@ -33,12 +33,12 @@ class LuaBaseData
return 0;
}

static int LuaDoFile(lua_State *L)
static int LuaDoFile(Lolua::State *L)
{
if (lua_isnoneornil(L, 1))
return LUA_ERRFILE;

LuaVar<char const*> var(L, 1);
Lolua::Var<char const*> var(L, 1);
char const *filename = var.V();// lua_tostring(L, 1);
int status = LUA_ERRFILE;

@@ -67,25 +67,28 @@ class LuaBaseData
}
};

namespace Lolua
{

//-----------------------------------------------------------------------------
LuaLoader::LuaLoader()
Loader::Loader()
{
m_lua_state = luaL_newstate();
lua_atpanic(m_lua_state, LuaBaseData::LuaPanic);
luaL_openlibs(m_lua_state);

/* Override dofile() */
LuaFunction do_file(m_lua_state, "dofile", LuaBaseData::LuaDoFile);
Lolua::Function do_file(m_lua_state, "dofile", LuaBaseData::LuaDoFile);
}

//-----------------------------------------------------------------------------
LuaLoader::~LuaLoader()
Loader::~Loader()
{
lua_close(m_lua_state);
}

//-----------------------------------------------------------------------------
bool LuaLoader::ExecLua(String const &lua)
bool Loader::ExecLua(String const &lua)
{
const char* c = lua_pushstring(m_lua_state, lua.C());
int status = LuaBaseData::LuaDoFile(m_lua_state);
@@ -93,10 +96,12 @@ bool LuaLoader::ExecLua(String const &lua)
}

//-----------------------------------------------------------------------------
lua_State* LuaLoader::GetLuaState()
Lolua::State* Loader::GetLuaState()
{
return m_lua_state;
}

} /* namespace Lolua */

} /* namespace lol */


+ 549
- 61
src/application/baselua.h View File

@@ -12,42 +12,137 @@
//

#include "lua/lua.hpp"
#include "lua/luawrapper.hpp"
//#include "lua/luawrapper.hpp"

#pragma once

namespace lol
{

//-----------------------------------------------------------------------------
namespace Lolua
{

//-----------------------------------------------------------------------------
typedef luaL_Reg ClassMethod;
typedef lua_State State;

//-----------------------------------------------------------------------------
template <typename T>
class ObjectDef
{
public:
ObjectDef() { }
virtual ~ObjectDef() { }
static ObjectDef<T>* New(State* l, int arg_nb)
{
UNUSED(l);
UNUSED(arg_nb);
ASSERT(false);
return nullptr;
}
static const char* GetClassName() { ASSERT(false); return nullptr; }
static const char* GetClassLibName() { ASSERT(false); return nullptr;; }
static const char* GetClassInstName() { ASSERT(false); return nullptr; }
static const ClassMethod* GetStaticMethods() { ASSERT(false); return nullptr; }
static const ClassMethod* GetInstanceMethods() { ASSERT(false); return nullptr; }

protected:
T* m_instance = nullptr;
};

//-----------------------------------------------------------------------------
// Class available to link C++ class to Lua methods
//--
class LuaObject
class Object
{
protected:
template<typename T, const char* name, const luaL_Reg* statics, const luaL_Reg* methods, T* (*ctor)(lua_State*)>
struct LuaLibrary
public:
//-------------------------------------------------------------------------
Object() { }
virtual ~Object() { }

//-------------------------------------------------------------------------
template <typename TLuaClass>
static void Register(State *l)
{
LuaLibrary() { }
void LoadTo(lua_State* l)
//Default statics
static const luaL_Reg default_statics[]
{
#define LOLUA_WRAPPER 1
#if LOLUA_WRAPPER
luaW_register<T>(l, name, statics, methods, ctor);
#else
luaL_newlib(L, statics);
luaL_newlib(L, methods);
#endif
}
};
{ "New", New<TLuaClass> },
{ "__gc", Del<TLuaClass> },
{ NULL, NULL }
};
//TODO: Touky: Implement that
//__tostring : ToString
//__add : Addition(+)
//__sub : Subtraction(-)
//__mul : Multiplication(*)
//__div : Division(/ )
//__mod : Modulos(%)
//__unm : Unary - , used for negation on numbers
//__concat : Concatenation(..)
//__eq : Equality(== )
//__lt : Less than(<)
//__le : Less than or equal to(<= )

//Create Static metatable
luaL_newmetatable(l, TLuaClass::GetClassLibName());
//Register default statics and template one
luaL_setfuncs(l, default_statics, 0);
luaL_setfuncs(l, TLuaClass::GetStaticMethods(), 0);
//Push funcs on metatable
lua_pushvalue(l, -1);
//Set the "__index" field of the metatable to point to itself, pops the stack
lua_setfield(l, -1, "__index");
//Set it global to validate the operation
lua_setglobal(l, TLuaClass::GetClassName());

//Repeat all the operations for instance metatable
luaL_newmetatable(l, TLuaClass::GetClassInstName());
luaL_setfuncs(l, TLuaClass::GetInstanceMethods(), 0);
lua_pushvalue(l, -1);
lua_setfield(l, -1, "__index");
//Don't set it to global, but pop the stack to hide the metatable
lua_pop(l, 1);
}

protected:
//-------------------------------------------------------------------------
template <typename TLuaClass>
static int New(State* l)
{
//Number of arguments
int n_args = lua_gettop(l);

//Create user data
TLuaClass** data = (TLuaClass**)lua_newuserdata(l, sizeof(TLuaClass*));
*data = TLuaClass::New(l, n_args);

//Retrieve instance table
luaL_getmetatable(l, TLuaClass::GetClassInstName());
//Set metatable to instance
lua_setmetatable(l, -2);
//Return 1 so Lua will get the UserData and clean the stack.
return 1;
}

//-------------------------------------------------------------------------
template <typename TLuaClass>
static int Del(State * l)
{
VarPtr<TLuaClass> obj(l, 1);
ASSERT(obj.V());
delete obj.V();
return 0;
}
};

//-----------------------------------------------------------------------------
//
//--
struct LuaFunction
struct Function
{
LuaFunction(lua_State* l, const char* name, int (*function)(lua_State*))
Function(State* l, const char* name, int(*function)(State*))
{
lua_pushcfunction(l, function);
lua_setglobal(l, name);
@@ -56,67 +151,113 @@ struct LuaFunction

//-----------------------------------------------------------------------------
template<typename T>
struct LuaVar
struct VarPtr
{
private:
T m_value = T(0);
protected:
T* m_value = nullptr;

public:
LuaVar() { }
LuaVar(T value) { m_value = value; }
LuaVar(lua_State* l, int index) { InnerGet(l, index); }
inline T& V() { return m_value; }
inline T& operator=(const T& value) { m_value = value; }
inline int Return(lua_State* l) { InnerPush(l); return 1; }
VarPtr() { }
VarPtr(T* value) { m_value = value; }
VarPtr(State* l, int index) { InnerGet(l, index); }
inline T* V() { return m_value; }
inline T* operator=(T* value) { m_value = value; }
inline int Return(State* l) { InnerPush(l); return 1; }

private:
void InnerGet(lua_State* l, int index) { ASSERT(false); }
void InnerPush(lua_State* l) { ASSERT(false); }
protected:
virtual void InnerGet(State* l, int index)
{
T** obj = static_cast<T**>(luaL_checkudata(l, index, T::GetClassInstName()));
m_value = obj ? *obj : nullptr;
}
void InnerPush(State* l)
{
T** data = (T**)lua_newuserdata(l, sizeof(T*));
*data = m_value;
}
};
//-----------------------------------------------------------------------------
template<typename T>
struct VarPtrLight
{
public:
VarPtrLight() : VarPtr() { }
VarPtrLight(T* value) : VarPtr(T* value) { }
VarPtrLight(State* l, int index) : VarPtr(State* l, int index) { }
protected:
virtual void InnerGet(State* l, int index)
{
T** obj = static_cast<T**>(luaL_testudata(l, index, T::GetClassInstName()));
m_value = obj ? *obj : nullptr;
}
};

//-----------------------------------------------------------------------------
template<typename T>
struct LuaPtr
struct Var
{
private:
T* m_value = nullptr;
T m_value;

public:
LuaPtr() { }
LuaPtr(T* value) { m_value = value; }
LuaPtr(lua_State* l, int index) { InnerGet(l, index); }
inline T* V() { return m_value; }
inline T* operator=(T* value) { m_value = value; }
inline int Return(lua_State* l) { InnerPush(l); return 1; }
Var() { InnerInit(); }
Var(T value) { m_value = value; }
Var(State* l, int index) { InnerGet(l, index); }
inline T& V() { return m_value; }
inline int Return(State* l) { InnerPush(l); return 1; }
inline Var<T>& operator-(const T& value) { m_value - value; return *this; }
inline Var<T>& operator+(const T& value) { m_value + value; return *this; }
inline Var<T>& operator*(const T& value) { m_value * value; return *this; }
inline Var<T>& operator/(const T& value) { m_value / value; return *this; }
inline Var<T>& operator=(const T& value) { m_value = value; return *this; }
inline Var<T>& operator-=(const T& value) { m_value -= value; return *this; }
inline Var<T>& operator+=(const T& value) { m_value += value; return *this; }
inline Var<T>& operator*=(const T& value) { m_value *= value; return *this; }
inline Var<T>& operator/=(const T& value) { m_value /= value; return *this; }
inline Var<T>& operator-(const Var<T>& o) { m_value - o.m_value; return *this; }
inline Var<T>& operator+(const Var<T>& o) { m_value + o.m_value; return *this; }
inline Var<T>& operator*(const Var<T>& o) { m_value * o.m_value; return *this; }
inline Var<T>& operator/(const Var<T>& o) { m_value / o.m_value; return *this; }
inline Var<T>& operator=(const Var<T>& o) { m_value = o.m_value; return *this; }
inline Var<T>& operator-=(const Var<T>& o) { m_value -= o.m_value; return *this; }
inline Var<T>& operator+=(const Var<T>& o) { m_value += o.m_value; return *this; }
inline Var<T>& operator*=(const Var<T>& o) { m_value *= o.m_value; return *this; }
inline Var<T>& operator/=(const Var<T>& o) { m_value /= o.m_value; return *this; }
inline bool operator==(const T& value) { return m_value == value; }
inline bool operator!=(const T& value) { return m_value != value; }
inline bool operator==(const Var<T>& o) { return m_value == o.m_value; }
inline bool operator!=(const Var<T>& o) { return m_value != o.m_value; }

private:
void InnerGet(lua_State* l, int index) { m_value = luaW_check<T>(l, index); }
void InnerPush(lua_State* l) { luaW_push<T>(l, m_value); }
void InnerInit() { m_value = T(0); }
void InnerGet(State* l, int index) { ASSERT(false); }
void InnerPush(State* l) { ASSERT(false); }
};

//-----------------------------------------------------------------------------
template<> inline void LuaVar<String> ::InnerGet(lua_State* l, int index) { m_value = lua_tostring(l, index); }
template<> inline void LuaVar<char const*>::InnerGet(lua_State* l, int index) { m_value = lua_tostring(l, index); }
template<> inline void LuaVar<double> ::InnerGet(lua_State* l, int index) { m_value = lua_tonumber(l, index); }
template<> inline void LuaVar<float> ::InnerGet(lua_State* l, int index) { m_value = (float)lua_tonumber(l, index); }
template<> inline void LuaVar<int32_t> ::InnerGet(lua_State* l, int index) { m_value = (int32_t)lua_tointeger(l, index); }
template<> inline void LuaVar<int64_t> ::InnerGet(lua_State* l, int index) { m_value = lua_tointeger(l, index); }
template<> inline void LuaVar<uint32_t> ::InnerGet(lua_State* l, int index) { m_value = lua_tounsigned(l, index); }

template<> inline void LuaVar<String> ::InnerPush(lua_State* l) { lua_pushstring(l, m_value.C()); }
template<> inline void LuaVar<char const*>::InnerPush(lua_State* l) { lua_pushstring(l, m_value); }
template<> inline void LuaVar<double> ::InnerPush(lua_State* l) { lua_pushnumber(l, m_value); }
template<> inline void LuaVar<float> ::InnerPush(lua_State* l) { lua_pushnumber(l, m_value); }
template<> inline void LuaVar<int32_t> ::InnerPush(lua_State* l) { lua_pushinteger(l, m_value); }
template<> inline void LuaVar<int64_t> ::InnerPush(lua_State* l) { lua_pushinteger(l, m_value); }
template<> inline void LuaVar<uint32_t> ::InnerPush(lua_State* l) { lua_pushunsigned(l, m_value); }
template<> inline void Var<String> ::InnerInit() { m_value = String(); }
template<> inline void Var<String> ::InnerGet(State* l, int index) { m_value = lua_tostring(l, index); }
template<> inline void Var<char const*>::InnerGet(State* l, int index) { m_value = lua_tostring(l, index); }
template<> inline void Var<double> ::InnerGet(State* l, int index) { m_value = lua_tonumber(l, index); }
template<> inline void Var<float> ::InnerGet(State* l, int index) { m_value = (float)lua_tonumber(l, index); }
template<> inline void Var<int32_t> ::InnerGet(State* l, int index) { m_value = (int32_t)lua_tointeger(l, index); }
template<> inline void Var<int64_t> ::InnerGet(State* l, int index) { m_value = lua_tointeger(l, index); }
template<> inline void Var<uint32_t> ::InnerGet(State* l, int index) { m_value = lua_tounsigned(l, index); }

template<> inline void Var<String> ::InnerPush(State* l) { lua_pushstring(l, m_value.C()); }
template<> inline void Var<char const*>::InnerPush(State* l) { lua_pushstring(l, m_value); }
template<> inline void Var<double> ::InnerPush(State* l) { lua_pushnumber(l, m_value); }
template<> inline void Var<float> ::InnerPush(State* l) { lua_pushnumber(l, m_value); }
template<> inline void Var<int32_t> ::InnerPush(State* l) { lua_pushinteger(l, m_value); }
template<> inline void Var<int64_t> ::InnerPush(State* l) { lua_pushinteger(l, m_value); }
template<> inline void Var<uint32_t> ::InnerPush(State* l) { lua_pushunsigned(l, m_value); }

//-----------------------------------------------------------------------------
class LuaLoader
class Loader
{
public:
LuaLoader();
virtual ~LuaLoader();
Loader();
virtual ~Loader();

bool ExecLua(String const &lua);

@@ -124,7 +265,7 @@ public:
T GetVar(String const &name)
{
lua_getglobal(m_lua_state, name.C());
LuaVar<T> var(m_lua_state, -1);
Var<T> var(m_lua_state, -1);
lua_pop(m_lua_state, 1);
return var.V();
}
@@ -138,10 +279,357 @@ public:
}

protected:
lua_State* GetLuaState();
Lolua::State* GetLuaState();

private:
lua_State* m_lua_state;
Lolua::State* m_lua_state;
};

//-----------------------------------------------------------------------------
//class T definition
//class T
//{
//public:
// int Ctor(lua_State* l) { return 0; }
// static const char* m_class_name;
// static const Class<T>::Variable* m_variables;
// static const Class<T>::Method* m_methods;
//};
/*
//-----------------------------------------------------------------------------
template<typename T>
class ClassTest
{
public:
//-----------------------------------------------------------------------------
struct Variable
{
const char* m_name;
int(*Getter)(lua_State*);
int(*Setter)(lua_State*);
};

//-----------------------------------------------------------------------------
struct Method
{
const char* m_name;
int(*Func)(lua_State*);
};

//Register: Register class in Lua. Leave library empty to store class in global scope.
static void Register(lua_State* l, const char *library = NULL)
{
if (library && strlen(library))
{
lua_getglobal(l, library);
//Create library if not present
if (lua_isnil(l, -1))
{
lua_newtable(l);
//Duplicate table pointer since setglobal pops the value
lua_pushvalue(l, -1);
lua_setglobal(l, library);
}
//lua_pushcfunction(l, &Class<T>::Ctor);
//lua_setfield(l, -2, T::m_class_name);
//lua_pop(l, 1);
}
else
{
//lua_pushcfunction(l, &Class<T>::Ctor);
//lua_setglobal(l, T::m_class_name);
}

luaL_newmetatable(l, T::m_class_name);
int metatable = lua_gettop(l);

//Register all m_methods: Register Name for fun_call and number for choice
for (int i = 0; T::m_methods[i].m_name; i++)
{
lua_pushstring(l, T::m_methods[i].m_name);
lua_pushcfunction(l, T::m_methods[i].Func);
lua_settable(l, metatable);
}

//lua_pushstring(l, "__gc");
//lua_pushcfunction(l, &Class<T>::Dtor);
//lua_settable(l, metatable);

//lua_pushstring(l, "__tostring");
//lua_pushcfunction(l, &Class<T>::ToString);
//lua_settable(l, metatable);

//lua_pushstring(l, "__eq");
//lua_pushcfunction(l, &Class<T>::Equals);
//lua_settable(l, metatable);

//lua_pushstring(l, "__index");
//lua_pushcfunction(l, &Class<T>::Getter);
//lua_settable(l, metatable);

//lua_pushstring(l, "__newindex");
//lua_pushcfunction(l, &Class<T>::Setter);
//lua_settable(l, metatable);

////Register all properties: Register Name for fun_call and number for choice
//for (int i = 0; T::m_variables[i].m_name; i++)
//{
// lua_pushstring(l, T::m_variables[i].m_name);
// lua_pushnumber(l, i);
// lua_settable(l, metatable);
//}

////Register all m_methods: Register Name for fun_call and number for choice
//for (int i = 0; T::m_methods[i].m_name; i++)
//{
// lua_pushstring(l, T::m_methods[i].m_name);
// //Add (1 << 8) to identify function on call
// lua_pushnumber(l, i | (1 << 8));
// lua_settable(l, metatable);
//}
}

};

//-----------------------------------------------------------------------------
template<typename T>
class Class
{
public:
//-----------------------------------------------------------------------------
struct Variable
{
const char* m_name;
int (T::*Getter)(lua_State*);
int (T::*Setter)(lua_State*);
};

//-----------------------------------------------------------------------------
struct Method
{
const char* m_name;
int (T::*Func)(lua_State*);
};

//-----------------------------------------------------------------------------
//Check: Raise an exception if FAIL
static T* Check(lua_State * l, int narg)
{
T** obj = static_cast <T **>(luaL_checkudata(l, narg, T::m_class_name));
return !obj ? nullptr : *obj;
}

//LightCheck: Returns nullptr if FAIL
static T* LightCheck(lua_State* l, int num_args)
{
T** obj = static_cast <T **>(luaL_testudata(l, num_args, T::m_class_name));
return !obj ? nullptr : *obj;
}

//Register: Register class in Lua. Leave library empty to store class in global scope.
static void Register(lua_State* l, const char *library = NULL)
{
if (library && strlen(library))
{
lua_getglobal(l, library);
//Create library if not present
if (lua_isnil(l, -1))
{
lua_newtable(l);
//Duplicate table pointer since setglobal pops the value
lua_pushvalue(l, -1);
lua_setglobal(l, library);
}
lua_pushcfunction(l, &Class<T>::Ctor);
lua_setfield(l, -2, T::m_class_name);
lua_pop(l, 1);
}
else
{
lua_pushcfunction(l, &Class<T>::Ctor);
lua_setglobal(l, T::m_class_name);
}

luaL_newmetatable(l, T::m_class_name);
int metatable = lua_gettop(l);

//lua_pushstring(l, "__gc");
//lua_pushcfunction(l, &Class<T>::Dtor);
//lua_settable(l, metatable);

//lua_pushstring(l, "__tostring");
//lua_pushcfunction(l, &Class<T>::ToString);
//lua_settable(l, metatable);

//lua_pushstring(l, "__eq");
//lua_pushcfunction(l, &Class<T>::Equals);
//lua_settable(l, metatable);

lua_pushstring(l, "__index");
lua_pushcfunction(l, &Class<T>::Getter);
lua_settable(l, metatable);

lua_pushstring(l, "__newindex");
lua_pushcfunction(l, &Class<T>::Setter);
lua_settable(l, metatable);

//Register all properties: Register Name for fun_call and number for choice
for (int i = 0; T::m_variables[i].m_name; i++)
{
lua_pushstring(l, T::m_variables[i].m_name);
lua_pushnumber(l, i);
lua_settable(l, metatable);
}

//Register all m_methods: Register Name for fun_call and number for choice
for (int i = 0; T::m_methods[i].m_name; i++)
{
lua_pushstring(l, T::m_methods[i].m_name);
//Add (1 << 8) to identify function on call
lua_pushnumber(l, i | (1 << 8));
lua_settable(l, metatable);
}
}

private:
//Ctor
static int Ctor(lua_State* l)
{
T* obj = new T(l);
T** lua_obj = static_cast<T**>(lua_newuserdata(l, sizeof(T*))); // Push value = userdata
*lua_obj = obj;

luaL_getmetatable(l, T::m_class_name); // Fetch global metatable T::classname
lua_setmetatable(l, -2);
return 1;
}

//Dtor
static int Dtor(lua_State* l)
{
T** lua_obj = static_cast<T**>(lua_touserdata(l, -1));
if (lua_obj && *lua_obj)
delete(*lua_obj);
return 0;
}

//AddInstance
static void AddInstance(lua_State* l, T* instance)
{
T** a = (T**)lua_newuserdata(l, sizeof(T*)); // Create userdata
*a = instance;

luaL_getmetatable(l, T::m_class_name);
lua_setmetatable(l, -2);
}

//----
static void GetVarIndex(lua_State* l)
{
lua_getmetatable(l, 1); //Look up the index of a m_name
lua_pushvalue(l, 2); //Push the m_name
lua_rawget(l, -2); //Get the index
}

//----
static void PrepareGetSet(lua_State* l)
{
lua_pop(l, 2); // Pop metatable and idx
lua_remove(l, 1); // Remove userdata
lua_remove(l, 1); // Remove [key]
}

//Getter: Call a func or a getter var
static int Getter(lua_State* l)
{
GetVarIndex(l);
//Check if we got a valid index
if (lua_isnumber(l, -1))
{
int idx = lua_tonumber(l, -1);
T** obj = static_cast<T**>(lua_touserdata(l, 1));
lua_pushvalue(l, 3);

//It's a method
if (idx & (1 << 8))
{
//Push the Method index and call the function
lua_pushnumber(l, idx ^ (1 << 8));
lua_pushlightuserdata(l, obj);
lua_pushcclosure(l, &Class<T>::CallMethod, 2);
// Return a Method
return 1;
}
else
{
PrepareGetSet(l);
return ((*obj)->*(T::m_variables[idx].Getter))(l);
}
}
return 1;
}

//Getter: Class a setter var or error if func
static int Setter(lua_State* l)
{
GetVarIndex(l);
//Check if we got a valid index
if (lua_isnumber(l, -1))
{
int idx = lua_tonumber(l, -1);
T** obj = static_cast<T**>(lua_touserdata(l, 1));
if (!obj || !*obj)
{
luaL_error(l, "Internal error, no object given!");
return 0;
}

//Try to set a Method - FAIL
if (idx & (1 << 8))
{
String s = String::Printf("Trying to set the method [%s] of class [%s]", (*obj)->T::m_methods[idx ^ (1 << 8)].m_name, T::m_class_name);
luaL_error(l, s.C());
return 0;
}
else
{
PrepareGetSet(l);
return ((*obj)->*(T::m_variables[idx].Setter))(l);
}
}
return 0;
}

//CallMethod: Actually calls the method on the object
static int CallMethod(lua_State* l)
{
int i = (int)lua_tonumber(l, lua_upvalueindex(1));
T** obj = static_cast <T**>(lua_touserdata(l, lua_upvalueindex(2)));
return ((*obj)->*(T::m_methods[i].Func))(l);
}

//ToString:
static int ToString(lua_State* l)
{
T** obj = static_cast<T**>(lua_touserdata(l, -1));
if (obj)
lua_pushfstring(l, "%s (%p)", T::m_class_name, (void*)*obj);
else
lua_pushstring(l, "Empty object");
return 1;
}

//Equals:
static int Equals(lua_State* l)
{
T** obj1 = static_cast<T**>(lua_touserdata(l, -1));
T** obj2 = static_cast<T**>(lua_touserdata(l, 1));
lua_pushboolean(l, *obj1 == *obj2);
return 1;
}
};
*/

} /* namespace Lolua */

} /* namespace lol */

+ 1
- 14
src/world.cpp View File

@@ -14,8 +14,6 @@
#include <cstdlib>
#include <ctype.h>

//#include "lua/lua.hpp"

namespace lol
{

@@ -36,21 +34,10 @@ World g_world;
* Public World class
*/

const luaL_Reg test1Lua::m_statics[] = { { "getTest", test1Lua::getTest }, { NULL, NULL } };
const luaL_Reg test1Lua::m_methods[] = { { NULL, NULL } };
const char test1Lua::m_class[] = "test1";

World::World()
: LuaLoader()
: Lolua::Loader()
{
g_world_data.m_lua_state = GetLuaState();
//------ DEBUG TEST
//m_test1.LoadTo(GetLuaState());
//luaL_loadfile(GetLuaState(), "lua/init.lua");
//LuaVar<int32_t> var(GetLuaState(), 1);
//test1Lua::Library m_test1(GetLuaState());
//------ DEBUG TEST

}

World::~World()


+ 1
- 41
src/world.h View File

@@ -18,51 +18,11 @@
namespace lol
{

class test1
{
public:
test1() {}
static int getTest(int i1, String s2)
{
return -1;
}
};

class test1Lua : public LuaObject
{
public:
test1Lua()
{
}
static test1* New(lua_State* L)
{
return new test1();
}
static int getTest(lua_State* L)
{
LuaVar<int> i1(L, 1);
LuaVar<String> s2(L, 2);
LuaVar<int64_t> res = (int64_t)test1::getTest(i1.V(), s2.V());
return res.Return(L);
}

private:
static const luaL_Reg m_statics[];
static const luaL_Reg m_methods[];
static const char m_class[];

public:
typedef LuaLibrary<test1, m_class, m_statics, m_methods, test1Lua::New> Library;
};

class World : public LuaLoader
class World : public Lolua::Loader
{
public:
World();
virtual ~World();

protected:
test1Lua::Library m_test1;
};

extern World g_world;


Loading…
Cancel
Save