rapptz / sol Goto Github PK
View Code? Open in Web Editor NEWA C++11 Lua wrapper
License: MIT License
A C++11 Lua wrapper
License: MIT License
54: const static std::array<std::string, 2> removals = { "struct ", "class " };
55: const static std::array<std::string, 2> replacements = { "::", "_" };
missing braces around initializer for 'std::arraystd::basic_string<char, 2u>::value_type [2] {aka std::basic_string [2]}' [-Wmissing-braces] demangle.hpp
missing braces around initializer for 'std::arraystd::basic_string<char, 2u>::value_type [2] {aka std::basic_string [2]}' [-Wmissing-braces] demangle.hpp
here is fix:
const static std::array<std::string, 2> removals = {{ "struct ", "class " }};
const static std::array<std::string, 2> replacements = {{ "::", "_" }};
Please add std::function in get method:
inline std::function<void()> get(typesstd::function<void()>, lua_State* L, int index = -1)
{
if(!lua_isfunction(L, index))
{
return {}; // maybe error?
};
lua_pushvalue(L, index);
int func = luaL_ref(L, LUA_REGISTRYINDEX);
return [func, L]()
{
lua_rawgeti(L, LUA_REGISTRYINDEX, func);
if(lua_isfunction(L, -1))
{
if(lua_pcall(L, 0, 0, 0))
{} // maybe error?
}
luaL_unref(L, LUA_REGISTRYINDEX, func);
};
}
example:
void testFunc(std::function<void()> f)
{
f();
}
A:testFunc(function() print("hello std::function") end)
Hi, I found this library do not use lua_pcall. I prefer to call a lua function with a message handler to offer a stack trace in error. so a function like lua.where() and lua.error([msg before where]) is good. have some plans to support this?
Userdata is becoming null for some reason when passed to a method of another userdata class. When used by the same class there's no problem. Simple test case:
struct Vec2 {
float x = 0;
float y = 0;
Vec2(float x_, float y_) : x{x_}, y{y_} {}
};
struct Incr {
Vec2 incr(const Vec2& v) {
return Vec2(v.x + 1, v.y + 1); // Eek! v is nullptr
}
};
lua.new_userdata<Vec2, float, float>("Vec2");
lua.new_userdata<Incr>("Incr", "incr", &Incr::incr);
lua.script("a = Vec2.new(10, 20)\n"
"i = Incr.new()\n"
"b = i:incr(v)\n"
"print(b.x, b.y)");
Is it possible to bind a template member function?
I'm trying to bind a varient class.
I've tried
m_lua.new_usertype<Test::Param>(
"Param",
"get_bool", &Test::Param::get<bool>
);
That produces error, expecting 3 arguments
and (although I didn't have hope in this one.)
m_lua.new_usertype<Test::Param>(
"Param",
"get_bool", static_cast<bool (Test::Param::*) ()>( &Test::Param::get<bool> )
);
I wrote some purposefully bad Lua code. I tried catching a sol::error after calling "open_file" but the C++ just SEGFAULTs.
At the moment the only way to create a table from C++ and returning it from a binded function is to use sol::table
as the return type like so:
sol::table stuff() {
}
However, the only way to actually create a sol::table
is through sol::state::create_table
which is very awkward to use with free functions. So you typically have to use a lambda or something like so:
int main() {
sol::state lua;
lua.set_function("stuff", [&lua](int x) {
auto&& t = lua.create_table();
// do stuff with table
});
It's very annoying and not very intuitive with current C++ code.
Instead, it would be nice if C++ containers returned tables as well.
Example:
std::vector<int> stuff() {
return { 1, 2, 3, 4, 5 };
}
int main() {
sol::state lua;
lua.set_function("stuff", stuff);
}
And then from the lua side:
local t = stuff()
for i = 1, #t do
print(t[i])
end
Would print 1 2 3 4 5
Hello. I'm having problems building sol on Ubuntu
rgb@woland:~/git/sol$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.2-19ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)
git clone Catch and sol
copy Catch/single_include/catch.hpp to sol/Catch/include/catch.hpp
python bootstrap.py
ninja
rgb@woland:~/git/sol$ ninja
[1/3] Compiling tests.cpp to obj/tests.o
FAILED: g++ -MMD -MF obj/tests.o.d -c -Wall -Wextra -pedantic -pedantic-errors -std=c++11 -DNDEBUG -O3 -I"." -I"Catch/include" -Werror tests.cpp -o obj/tests.o
In file included from ./sol/reference.hpp:25:0,
from ./sol/object.hpp:25,
from ./sol/proxy.hpp:26,
from ./sol/table.hpp:25,
from ./sol/state.hpp:26,
from ./sol.hpp:25,
from tests.cpp:3:
./sol/types.hpp:25:19: fatal error: lua.hpp: No such file or directory
#include <lua.hpp>
^
compilation terminated.
ninja: build stopped: subcommand failed.
Output:
[1/3] Compiling tests.cpp to obj/tests.o
FAILED: g++ -MMD -MF obj/tests.o.d -c -Wall -Wextra -pedantic -pedantic-errors -std=c++11 -DNDEBUG -O3 -I"." -I"Catch/include" -I"/usr/include/lua5.1" -Werror tests.cpp -o obj/tests.o
In file included from ./sol/object.hpp:26:0,
from ./sol/proxy.hpp:26,
from ./sol/table.hpp:25,
from ./sol/state.hpp:26,
from ./sol.hpp:25,
from tests.cpp:3:
./sol/stack.hpp: In static member function ‘static U sol::stack::getter<T, X>::get(lua_State_, int)’:
./sol/stack.hpp:73:39: error: there are no arguments to ‘lua_tounsigned’ that depend on a template parameter, so a declaration of *‘lua_tounsigned’_ must be available [-fpermissive]
return lua_tounsigned(L, index);^M
^
./sol/stack.hpp:73:39: note: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)
In file included from ./sol/state.hpp:26:0,
from ./sol.hpp:25,
from tests.cpp:3:
./sol/table.hpp: In member function ‘size_t sol::table::size() const’:
./sol/table.hpp:108:38: error: ‘lua_rawlen’ was not declared in this scope
return lua_rawlen(state(), -1);^M
^
./sol/table.hpp: In member function ‘sol::table& sol::table::set_fx(std::true_type, T&&, TFx&&, TObj&&)’:
./sol/table.hpp:187:53: error: there are no arguments to ‘luaL_setfuncs’ that depend on a template parameter, so a declaration of ‘luaL_setfuncs’ must be available [-fpermissive]
luaL_setfuncs(state(), funcreg, upvalues + 1);^M
^
./sol/table.hpp: In member function ‘sol::table& sol::table::set_fx(std::false_type, T&&, TFx&&)’:
./sol/table.hpp:206:49: error: there are no arguments to ‘luaL_setfuncs’ that depend on a template parameter, so a declaration of ‘luaL_setfuncs’ must be available [-fpermissive]
luaL_setfuncs(state(), funcreg, upvalues);^M
^
./sol/table.hpp: In member function ‘sol::table& sol::table::set_fx(T&&, std::unique_ptrsol::base_function)’:
./sol/table.hpp:236:42: error: there are no arguments to ‘luaL_setfuncs’ that depend on a template parameter, so a declaration of ‘luaL_setfuncs’ must be available [-fpermissive]
luaL_setfuncs(state(), funcreg, 1);^M
I'd be grateful for your advice.
^
Having const
, volatile
, or reference qualifiers in function parameters causes (many) compiler errors.
Minimal test case:
#include <sol.hpp>
#include <iostream>
struct test {
void g(const std::string& str) {
std::cout << str << '\n';
}
};
int main() {
sol::state lua;
lua.new_userdata<test>("test", "g", &test::g);
lua.script("x = test.new()\n"
"x:g('hello')");
}
As of now, I couldn't figure out a better way to access a Derived's class method without overriding the Base's method. Example:
class Base {
public:
Base( int a_num ) : m_num(a_num) {}
int get_num() {
return m_num;
}
protected:
int m_num;
};
class Derived : public Base {
public:
Derived( int a_num ) : Base(a_num) {}
int get_num_10() {
return 10 * m_num;
}
int get_num() {
return Base::get_num();
}
};
//-------------------------------------------------------------//
sol::constructors<sol::types<int>> l_ctor_base;
sol::userdata<Base> l_userdata_base( "Base", l_ctor_base, "get_num", &Base::get_num );
l_lua.set_userdata( l_userdata_base );
l_lua.script( "base = Base.new( 5 )" );
l_lua.script( "print( base:get_num() )" );
sol::constructors<sol::types<int>> l_ctor_derived;
sol::userdata<Derived> l_userdata_derived( "Derived", l_ctor_derived, "get_num", &Derived::get_num, "get_num_10", &Derived::get_num_10 );
l_lua.set_userdata( l_userdata_derived );
l_lua.script( "derived = Derived.new( 7 )" );
l_lua.script( "print( derived:get_num_10() )" );
l_lua.script( "print( derived:get_num() )" );
//------------------------------------------//
If I don't override get_num in Derived, I get the following error when registering get_num:
no matching function for call to ‘sol::userdata::build_function_tables(const char [8], int (Base::)(), const char [11], int (Derived::)())’
It would be interesting to support inheritance, but if not, at least to come up with an workaround to this, since overriding all of the methods is usually not desired.
Other than that, great project! Keep up the good work :D
This is sort of two requests. I'm wondering what to do about statics. For example, the Vec2 class that I'm using as a test case has static methods like Vec2f::zero()
and Vec2f::xAxis()
which can be useful as alternate constructors. It'd be nice to be able to call these from Lua like Vec2.xAxis()
. Is there currently a way to do this?
It would also be great to allow free functions for adding functionality that the underlying class does not support:
"__tostring", [](const Vec2<T>& v) {
return "[" + std::to_string(v.x) + ", " + std::to_string(v.y) + "]";
}
Although, this could probably be added in a Lua script after the userdata is created.. But doing it from C++ might be cleaner.
ClassA* popClass()
{
return this;
}
local A = ClassA:new()
local B = A:popClass()
B:test() -- here is crash
error code:
terminate called after throwing an instance of 'sol::error'
what(): lua: error: script.lua:4: attempt to index local 'B' (a userdata value)
Hi! I'm trying to bind a class that returns instances of it's own type. Here's a simplified example:
struct Vec {
float x, y, z;
Vec(float x, float y, float z) : x{x}, y{y}, z{z} {}
float length() {
return sqrtf(x*x + y*y + z*z);
}
Vec normalized() {
float invS = 1 / length();
return {x * invS, y * invS, z * invS};
}
};
sol::state lua;
lua.open_libraries(sol::lib::base);
sol::constructors<sol::types<float, float, float>> ctor;
sol::userdata<Vec> udata("Vec", ctor,
"normalized", &Vec::normalized,
"length", &Vec::length);
lua.set_userdata(udata);
This script works:
lua.script("v = Vec.new(1, 2, 3)\n"
"print(v:length())");
// --> 3.7416574954987
But this one fails:
lua.script("v = Vec.new(1, 2, 3)\n"
"print(v:normalized():length())");
// --> EXC_BAD_ACCESS
Is it possible to do this with sol, or am I missing something?
Hi
I am very new to github so please forgive my noobness: I started using Sol and managed to integrate it (it's very easy, no problem here) in my test program. I tried the following: load a lua file which has a generateDungeon function which returns a 4096 elements table. Then in C++ I do the following:
sol::function dungeonFunc = luaVM.get<sol::function>("generateDungeon");
sol::table dungeon = dungeonFunc.call<sol::table>();
Everything works flawlessly but when I want to read all the values from table:
for(std::size_t i = 1; i <= dungeon.size(); ++ i)
{
const auto value = dungeon.get<int>(i);
// etc...
}
loop finishes but I have seg fault errors in random places. I tested commenting here and there and my conclusion points to sol::table::size(). I took dungeon.size() call out from for loop:
auto dungeonSize = dungeon.size();
for(std::size_t i = 1; i <= dungeonSize; ++ i)
With this change everything works. I checked sol::table:size() and we have the following:
size_t size() const {
push();
return lua_rawlen(state(), -1);
}
With my total lack of knowledge of how sol and lua work, I would say that push() makes some stack get bigger in each call to size() and finally makes my app crash. Is it possible this to be a bug?
Thanks for your library by the way ;)
Regards
Is there a means for checking for an existence of a key within a sol::table
?
Additionally, when using sol::table::operator[]
, it returns a sol::proxy
. However, this type has no means of checking the type of the underlying value.
Something like this might be neat:
sol::table tbl; // assume it's initialized
if (auto prox = tbl["my_key"])
{
// use prox
}
else
{
// prox doesn't actually exist
}
A method such as exists()
would be useful, too. I took this syntax suggestion from boost's optional
type.
Operator overloading has been mentioned a couple times in the issues, but I can't find an example. Is it possible to add an operator overload to a userdata? I have tried something like this, without luck:
sol::userdata<Vec2f> udata("Vec2", ctor, "__add", &Vec2f::operator+);
I'd be happy to add this to the userdata example if it's possible and someone can show me how 😄
There's no documentation for sol. Or well, any other lua binding library really. Should probably fix that.
It's an on going progress and they'll be under the docs
branch. They'll be published on a github page.
Any plans on adding iteration capabilities in sol::table ?
Hello, I creating benchmark (https://github.com/bagobor/cpp2lua-buindings-battle) for lua binding libraries and found that Sol failed to build with modern Visual Studio 2015
template<class F>
struct check_deducible_signature {
template<class G>
static auto test(int) -> decltype(&G::operator(), void());
template<class>
static auto test(...) -> struct nat;
using type = std::is_void<decltype(test<F>(0))>;
};
template static auto test(...) -> struct nat; leads to compile error. :(
May be you have an idea how to fix it. I'm not so proficient with modern 'meta' magic.
I'm not exactly sure what's going on here, but clang gives me this fixit error when compiling proxy.hpp:
In file included from ../deps/sol/sol.hpp:25:
In file included from ../deps/sol/sol/state.hpp:26:
In file included from ../deps/sol/sol/table.hpp:25:
../deps/sol/sol/proxy.hpp:45:20: error: use 'template' keyword to treat 'get' as a dependent template name
return tbl.get<T>(key);
^
template
../deps/sol/sol/proxy.hpp:108:20: error: use 'template' keyword to treat 'get' as a dependent template name
return tbl.get<function>(key)(types<Ret...>(), std::forward<Args>(args)...);
^
template
Changing the those lines like so resolves the error:
return tbl.get<T>(key);
→ return tbl.template get<T>(key);
Is this a proper fix?
My clang --version just in case:
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Hi
Is there a way to register a function from C++ so it is contained in a table? So I can call from Lua this way:
local v = MyStuff.doSomething(...)
Thanks
Hi,
I'm totally new to sol, so maybe my compiling error is stupid.
I'm working on Windows 64 bits (compiling in 32 bits) with Code::Blocks 13.12.
I recompiled lua 5.2.3 like 10 minutes ago.
This simple code won't compile:
#include <sol.hpp>
#include <cassert>
struct vars {
int boop = 0;
};
int main() {
sol::state lua;
lua.new_userdata<vars>("vars", "boop", &vars::boop);
lua.script("local beep = vars.new()\n"
"beep.boop = 1");
assert(lua.get<vars>("beep").boop == 1);
}
When i use a simple examples (basic.cpp or variables.cpp), the code compile and works as expected but when i use the set_function or new_userdata functions like in the code above, i get the following error:
||=== Build: Debug in lua-test (compiler: GNU GCC Compiler) ===|
C:\...\sol-master\sol\traits.hpp||In instantiation of 'struct sol::detail::check_deducible_signature<void (vars::*)()>':|
...\sol-master\sol\traits.hpp|159|required from 'struct sol::has_deducible_signature<void (vars::*)()>'|
...\sol-master\sol\traits.hpp|239|required from 'struct sol::function_traits<void (vars::*)()>'|
...\sol-master\sol\traits.hpp|252|required from 'struct sol::detail::member_traits<void (vars::*)(), false>'|
...\sol-master\sol\function_types.hpp|37|required from 'struct sol::detail::functor<vars, void (vars::*)(), void>'|
...\sol-master\sol\function_types.hpp|377|required from 'struct sol::userdata_function_core<void (vars::*)(), vars>'|
...\sol-master\sol\function_types.hpp|500|required from 'struct sol::userdata_indexing_function<void (vars::*)(), vars>'|
...\lua\sol-master\sol\userdata.hpp|165|required from 'void sol::userdata<T>::build_function_tables(sol::userdata<T>::function_map_t*&, sol::userdata<T>::function_map_t*&) [with unsigned int N = 0u; T = vars; sol::userdata<T>::function_map_t = std::unordered_map<std::basic_string<char>, std::pair<std::unique_ptr<sol::base_function>, bool> >]'|
...\lua\sol-master\sol\userdata.hpp|301|required from 'void sol::userdata<T>::build_function_tables(sol::userdata<T>::function_map_t*&, sol::userdata<T>::function_map_t*&, std::string, Fx&&, Args&& ...) [with unsigned int N = 0u; Fx = int vars::*; Args = {}; T = vars; sol::userdata<T>::function_map_t = std::unordered_map<std::basic_string<char>, std::pair<std::unique_ptr<sol::base_function>, bool> >; std::string = std::basic_string<char>]'|
...\sol\userdata.hpp|330|required from 'sol::userdata<T>::userdata(std::string, sol::constructors<CArgs ...>, Args&& ...) [with Args = {const char (&)[5], int vars::*}; CArgs = {sol::types<>}; T = vars; std::string = std::basic_string<char>]'|
...\sol-master\sol\state.hpp|169|required from 'sol::state& sol::state::new_userdata(const string&, sol::constructors<CArgs ...>, Args&& ...) [with Class = vars; CArgs = {sol::types<>}; Args = {const char (&)[5], int vars::*}; sol::state = sol::state; std::string = std::basic_string<char>]'|
...\sol-master\sol\state.hpp|164|required from 'sol::state& sol::state::new_userdata(const string&, Args&& ...) [with Class = vars; CTor = {}; Args = {const char (&)[5], int vars::*}; sol::state = sol::state; std::string = std::basic_string<char>]'|
...\lua-test\main.cpp|10|required from here|
...\sol-master\sol\traits.hpp|154|error: invalid use of incomplete type 'struct sol::detail::nat'|
...\sol-master\sol\traits.hpp|152|error: forward declaration of 'struct sol::detail::nat'|
...\sol-master\sol\traits.hpp||In instantiation of 'struct sol::function_traits<void (vars::*)()>':|
...\sol-master\sol\traits.hpp|252|required from 'struct sol::detail::member_traits<void (vars::*)(), false>'|
...\sol-master\sol\function_types.hpp|37|required from 'struct sol::detail::functor<vars, void (vars::*)(), void>'|
...\lua\sol-master\sol\function_types.hpp|377|required from 'struct sol::userdata_function_core<void (vars::*)(), vars>'|
...\lua\sol-master\sol\function_types.hpp|500|required from 'struct sol::userdata_indexing_function<void (vars::*)(), vars>'|
...\lua\sol-master\sol\userdata.hpp|165|required from 'void sol::userdata<T>::build_function_tables(sol::userdata<T>::function_map_t*&, sol::userdata<T>::function_map_t*&) [with unsigned int N = 0u; T = vars; sol::userdata<T>::function_map_t = std::unordered_map<std::basic_string<char>, std::pair<std::unique_ptr<sol::base_function>, bool> >]'|
...\lua\sol-master\sol\userdata.hpp|301|required from 'void sol::userdata<T>::build_function_tables(sol::userdata<T>::function_map_t*&, sol::userdata<T>::function_map_t*&, std::string, Fx&&, Args&& ...) [with unsigned int N = 0u; Fx = int vars::*; Args = {}; T = vars; sol::userdata<T>::function_map_t = std::unordered_map<std::basic_string<char>, std::pair<std::unique_ptr<sol::base_function>, bool> >; std::string = std::basic_string<char>]'|
...\lua\sol-master\sol\userdata.hpp|330|required from 'sol::userdata<T>::userdata(std::string, sol::constructors<CArgs ...>, Args&& ...) [with Args = {const char (&)[5], int vars::*}; CArgs = {sol::types<>}; T = vars; std::string = std::basic_string<char>]'|
...\lua\sol-master\sol\state.hpp|169|required from 'sol::state& sol::state::new_userdata(const string&, sol::constructors<CArgs ...>, Args&& ...) [with Class = vars; CArgs = {sol::types<>}; Args = {const char (&)[5], int vars::*}; sol::state = sol::state; std::string = std::basic_string<char>]'|
...\lua\sol-master\sol\state.hpp|164|required from 'sol::state& sol::state::new_userdata(const string&, Args&& ...) [with Class = vars; CTor = {}; Args = {const char (&)[5], int vars::*}; sol::state = sol::state; std::string = std::basic_string<char>]'|
...\lua-test\main.cpp|10|required from here|
...\sol-master\sol\traits.hpp|239|error: 'value' is not a member of 'sol::has_deducible_signature<void (vars::*)()>'|
...\sol-master\sol\function_types.hpp||In instantiation of 'struct sol::detail::functor<vars, void (vars::*)(), void>':|
...\sol-master\sol\function_types.hpp|377|required from 'struct sol::userdata_function_core<void (vars::*)(), vars>'|
...\sol-master\sol\function_types.hpp|500|required from 'struct sol::userdata_indexing_function<void (vars::*)(), vars>'|
...\sol-master\sol\userdata.hpp|165|required from 'void sol::userdata<T>::build_function_tables(sol::userdata<T>::function_map_t*&, sol::userdata<T>::function_map_t*&) [with unsigned int N = 0u; T = vars; sol::userdata<T>::function_map_t = std::unordered_map<std::basic_string<char>, std::pair<std::unique_ptr<sol::base_function>, bool> >]'|
...\sol-master\sol\userdata.hpp|301|required from 'void sol::userdata<T>::build_function_tables(sol::userdata<T>::function_map_t*&, sol::userdata<T>::function_map_t*&, std::string, Fx&&, Args&& ...) [with unsigned int N = 0u; Fx = int vars::*; Args = {}; T = vars; sol::userdata<T>::function_map_t = std::unordered_map<std::basic_string<char>, std::pair<std::unique_ptr<sol::base_function>, bool> >; std::string = std::basic_string<char>]'|
...\sol-master\sol\userdata.hpp|330|required from 'sol::userdata<T>::userdata(std::string, sol::constructors<CArgs ...>, Args&& ...) [with Args = {const char (&)[5], int vars::*}; CArgs = {sol::types<>}; T = vars; std::string = std::basic_string<char>]'|
...\sol-master\sol\state.hpp|169|required from 'sol::state& sol::state::new_userdata(const string&, sol::constructors<CArgs ...>, Args&& ...) [with Class = vars; CArgs = {sol::types<>}; Args = {const char (&)[5], int vars::*}; sol::state = sol::state; std::string = std::basic_string<char>]'|
...\sol-master\sol\state.hpp|164|required from 'sol::state& sol::state::new_userdata(const string&, Args&& ...) [with Class = vars; CTor = {}; Args = {const char (&)[5], int vars::*}; sol::state = sol::state; std::string = std::basic_string<char>]'|
...\lua-test\main.cpp|10|required from here|
...\sol-master\sol\function_types.hpp|37|error: no type named 'args_type' in 'struct sol::detail::member_traits<void (vars::*)(), false>'|
...\sol-master\sol\function_types.hpp|38|error: no type named 'return_type' in 'struct sol::detail::member_traits<void (vars::*)(), false>'|
...\sol-master\sol\function_types.hpp|59|error: no type named 'return_type' in 'struct sol::detail::member_traits<void (vars::*)(), false>'|
...\sol-master\sol\function_types.hpp||In member function 'int sol::userdata_indexing_function<Function, Tp>::fx_call(lua_State*) [with Tx = vars*; Function = void (vars::*)(); Tp = vars; lua_State = lua_State]':|
...\sol-master\sol\function_types.hpp|540|warning: control reaches end of non-void function [-Wreturn-type]|
...\sol-master\sol\function_types.hpp||In member function 'int sol::userdata_indexing_function<Function, Tp>::fx_call(lua_State*) [with Tx = vars; Function = void (vars::*)(); Tp = vars; lua_State = lua_State]':|
...\sol-master\sol\function_types.hpp|540|warning: control reaches end of non-void function [-Wreturn-type]|
||=== Build failed: 6 error(s), 35 warning(s) (0 minute(s), 0 second(s)) ===|
Can someone tell me what i did wrong?
Thanks a lot in advance :)
There are some warnings that cause issues w.r.t. compilation (mainly Clang). Through the use of #pragma
and _Pragma
you could programmatically disable some warnings that just make things a headache.
Example:
#define STRINGIZE_PRAGMA(x) _Pragma(#x)
#if defined(__clang__)
#define PRAGMA(x) STRINGIZE_PRAGMA (clang x)
#elif defined (__GNUC__)
#define PRAGMA(x) STRINGIZE_PRAGMA (GCC x)
#endif
PRAGMA(diagnostic push)
PRAGMA(diagnostic ignored "-Wwhatever")
// some code here
PRAGMA(diagnostic pop)
Some candidates for programmatic removal include:
Probably others as time goes on.
LuaJIT (a lot of uses) is Lua 5.1 syntax and API interface compatible, could sol support it ?
I'm creating a tower defense game that uses Lua as a scripting engine.
When compiling with both g++ and clang++ I get the following error.
include/sol/sol/stack.hpp:100:31: error: use of undeclared identifier "lua_tounsigned"
return static_cast<U>(lua_tounsigned(L, index));
I am using the following command to compile:
g++ -Wall -Wno-format -Wno-unused-variable -c -g -O0 -fbuiltin -fpermissive -std=c++11 -I include -I src/include <FILES> -Llib <*snip*> -llua -o ./bin/Tower
I believe there error crops up when I'm defining my classes to use inside Lua. I created a class called LuaScript
. Here are the .h and .cpp files
LuaScript.h
#ifndef _LUA_SCRIPT_H
#define _LUA_SCRIPT_H
#include <string>
#include "lua/selene.h"
#include "sol/sol.hpp"
class LuaScript {
public:
LuaScript(bool loadedClasses = true);
bool isLoaded() { return _loaded; }
void setLoaded(bool b) { _loaded = b; }
void loadScript(const std::string& name);
sol::state lua;
protected:
bool _loaded;
void defineEnemy();
void defineTower();
void defineObject();
void defineTarget();
void defineMap();
void defineStats();
};
#endif
LuaScript.cpp
#include "LuaScript.h"
<*Includes have been snipped*>
LuaScript::LuaScript(bool defineClasses) {
_loaded = false;
lua.open_libraries(sol::lib::base, sol::lib::math, sol::lib::table,
sol::lib::package, sol::lib::math, sol::lib::debug);
if (defineClasses) {
defineTarget();
defineObject();
defineTower();
defineEnemy();
defineMap();
defineStats();
}
}
void LuaScript::loadScript(const std::string& name) {
lua.open_file(name);
setLoaded(true);
}
void LuaScript::defineTower() {
sol::constructors<sol::types<Map*, float, float, Stats>> towerCon;
sol::userdata<Tower> towerUserData (
"Tower", towerCon,
// Target methods
"getX", &Tower::getX,
"getY", &Tower::getY,
"setPosition", &Tower::setPosition,
"isSimpleTarget", &Tower::isSimpleTarget,
// Object methods
"contains", &Tower::contains,
"applyStat", &Tower::applyStat,
"setStats", &Tower::setStats,
"getSpeed", &Tower::getSpeed,
"getRange", &Tower::getRange,
"getFireRate", &Tower::getFireRate,
"getDamage", &Tower::getDamage,
"getAccel", &Tower::getAccel,
"getProjSpeed", &Tower::getProjSpeed,
//"setRange", &Tower::setRange, // ERROR
// Tower methods
"getProjectile", &Tower::getProjectile,
"setProjectile", &Tower::setProjectile
);
lua.set_userdata(towerUserData);
}
void LuaScript::defineObject() {
<*snip*>
}
void LuaScript::defineTarget() {
<*snip*>
}
void LuaScript::defineMap() {
<*snip*>
}
void LuaScript::defineStats() {
<*snip*>
}
void LuaScript::defineEnemy() {
<*snip*>
}
All my Tower methods have been defined in Tower.cpp
and Tower.h
. Here are the relevant parts.
Tower.h
#ifndef _TOWER_H
#define _TOWER_H
#include "Target.h"
#include "Object.h"
#include "Stats.h"
class Tower : public Object {
public:
<*I've removed all irrelevant code*>
Tower(Map* map, float x, float y, Stats s);
~Tower();
void loadLua();
void setPosition(float x, float y);
Object* getProjectile() { return _projectile; }
void setProjectile(Object& o);
protected:
<*snip*>
};
#endif
If I uncomment "setRange", &Tower::setRange
I get the undeclared error, but commenting it out works fine.
Tower::setRange
is set inside Object.h, the parent class of Tower.
Object.h
#ifndef _OBJECT_H
#define _OBJECT_H
<*Includes have been snipped*>
class Object : public Target, public sf::Drawable, public sf::Transformable {
public:
Object();
Object(Map* map, float x, float y, int collRadius, Stats s);
virtual ~Object();
<*snip*>
int getSpeed() const { return _stats.speed + _baseStats.speed; }
int getRange() const { return _stats.range + _baseStats.range; }
float getFireRate() const { return _stats.fireRate + _baseStats.fireRate; }
float getDamage() const { return _stats.damage + _baseStats.damage; }
float getAccel() const { return _stats.accel + _baseStats.accel; }
float getProjSpeed() const { return _stats.projSpeed + _baseStats.projSpeed; }
// Stats setters
void setRange(int r) { _stats.range = r; } // ERROR method
<*snip*>
};
#endif
I don't understand why that specific method would cause issues with Sol. All the other methods I've declared work with Sol, and compile fine, but that method throws the error.
If I'm doing something wrong or I need to provide some more information let me so I can get this figured out.
Is there a way to select which version of a overloaded function to use when creating userdata? This is a class similar to the one I'm trying to bind:
struct vector {
float x = 0;
float y = 0;
vector() = default;
void set(float x_, float y_) { x = x_; y = y_; }
void set(const vector& v) { x = v.x; y = v.y; }
};
So given that there are two versions of set
, how do I choose which one to bind?
sol::userdata<vector>("vector", ctor, "set", &vector::set); // Doesn't work
Can't set a function inside a table, user made or otherwise. Doing it through sol::state::script
works just fine though.
Simple test case:
#include <sol.hpp>
#include <iostream>
#include <iomanip>
int main() {
sol::state lua;
lua.open_libraries(sol::lib::base, sol::lib::os);
lua.get<sol::table>("os").set_function("fun", []() {
return "test";
});
lua.get<sol::table>("os").set("name", "windows");
lua.script("assert(os.fun() == \"test\")\n" // fails
"assert(os.name == \"windows\")");
}
Hi
I am currently programming a small home brew game and I plan to use Lua along with Sol. My idea is to somewhat use the model exposed by Unity and other game developing packages: the game entities (for example a zombie enemy) will be formed by different components (sprite or graphical representation, collider, etc). These components will be managed by the C++ part, while Lua will be "the client": it just asks for a collider, a sprite, etc. and uses them in some coherent way (for example collider determines the world position of the sprite). This is somewhat analog to how javascript deals with DOM objects provided by the browser.
So to implement that I thought I could create, to expose to Lua, a bunch of functions like the following:
std::size_t newSprite(const std::string& fileName);
void setSpritePosition(std::size_t spriteId, const Vector2D& position);
void removeSprite(std::size_t spriteId);
These functions would be implemented in order to call SpriteController, which with the spriteId would look up in its sprite list and modify the corresponding sprite object.
But on the other hand I can also expose C++ classes to Lua, for example:
class SpriteLua
{
public:
Sprite(const std::string& fileName)
{
mSprite = spriteController.load(fileName);
}
void setPosition(const Vector2D& position)
{
mSprite->setPosition(position);
}
...
...
private:
Sprite* mSprite;
};
The class approach seems faster and also more convenient to write in the Lua side (just manage Sprite instance instead of spriteSomething + spriteId + parameters, but I don't know the overhead, if it exists at all, of this second approach.
I know this can be a premature optimization case but I think I need to know both approach relative cost, it can decide how to do a substantial part of C++ <--> Lua communication of the game. Also I welcome any other suggestion about this or related issue.
Thanks
libjansson offers a c-style "any" iterator where you can fix values from the type like so. A similar API (that's less wonky since we're in C++) could probably be created and allowed for with table's begin()
and end()
syntax, using sol::object
for values and perhaps a new sol::key
type (since keys can only be integers or strings in lua
).
I'd be interested in doing this for version 2.0 later on!
template
struct getter<T&> {
static T& get(lua_State* L, int index = -1) {
void* udata = lua_touserdata(L, index);
T** obj = static_cast<T**>(udata);
return **obj;
}
};
after:
template
struct getter<T&> {
static T& get(lua_State* L, int index = -1) {
void* udata = lua_touserdata(L, index);
T* obj = static_cast<T*>(udata); // here change
return *obj; // here change
}
};
It's one thing I've put off for a while but I guess it's time to do it eventually. Currently there's no way to bind a C++ class to Lua. This would be a pretty neat feature to have. I'm using this issue for notes on how I'd implement it and/or design it.
One of the difficult things to do is generalising the constructor of a class or what happens when there are multiple constructors. I think for the best case it's better if I pass the constructor types in a variadic template along with the class type. It's probably also for the best to only support a single constructor rather than multiple, since Lua doesn't even have function overloading and overloaded functions don't work with sol anyway so there's no expectation of it working.
At the end of the day, in Lua classes are just tables with the __index meta table pointing to itself. So that shouldn't be too difficult. There's also support for member function pointers already, which I suppose is admittedly a much harder part than constructors.
Open ended questions I'll deal with later:
T::operator
.typeid
and demangling?Currently, sol
fails to pass a sol::table
as a parameter to a usertype
.
Minimum example:
class Foo {
public:
Foo(sol::table /*table*/) { }
};
int main() {
sol::state lua;
lua.new_usertype<Foo, sol::table>("Foo");
lua.script("a = Foo.new { a = \"wat\" }");
}
The error message is: lua: error: No matching constructor for the arguments provided
Hi guys
I recently developed a small script in python which allows to document easily Lua bindings done in C++ side. Perhaps it exists such a tool (some doxygen configuration or another program) but well, it was not a bad excuse to learn a little bit more python.
You can download it from there: https://github.com/iganinja/generic_doc_generator
Thanks.
Sandboxing is very usefull while you want to load more than one file (ex. for handlers, callbacks).
This code is not working under 5.2, function lua_setfenv is missing.
lua_State* l = L.get();
if(luaL_loadfile(state, filename.c_str())) {
lua_error(state);
return;
}
// create env table
lua_newtable( state );
int envTable = lua_gettop( state );
lua_newtable( state );
// set the env
lua_setfenv( state, -2 );
// copy _G
lua_newtable( state );
int __index = lua_gettop( state );
lua_pushstring( state, "__index" );
lua_getfield( state, LUA_GLOBALSINDEX, "_G" );
lua_settable( state, __index );
// set the metatable for the env table
lua_setmetatable( state, envTable );
// set the env
lua_pushvalue(state, -1);
lua_setfield(state, LUA_GLOBALSINDEX, name.c_str());
lua_setfenv( state, -2 );
lua_pcall(state, 0, -1, 0);
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.