Giter Club home page Giter Club logo

selene's Introduction

Selene

SEEKING NEW MAINTAINER

Selene would love to have a new home :) The project makes it very simple to interface from C++ to Lua but needs some love to manage pull requests, issues, Lua compatibility, and other improvements. I intend on creating a separate organization for Selene that I can continue to sit in and weigh in feedback as I have time, but will allow for multiple contributors. Please let me know if you're interested by emailing [email protected]. Of course, previous and current active maintainers will go to the front of the line, but everyone will be considered!

Best, Jeremy

Build Status

Simple C++11 friendly header-only bindings to Lua 5.1+.

Requirements

  • Cmake 2.8+
  • Lua 5.1+
  • C++11 compliant compiler

Usage

Selene is a headers-only library so you just need to include "selene.h" to use this project.

To build the tests, do the following:

mkdir build
cd build
cmake ..
make

This will build a test_runner executable that you can run. If you wish to include Lua from another location, you made pass the LUA_INCLUDE_DIR option to cmake (i.e. cmake .. -DLUA_INCLUDE_DIR=/path/to/lua/include/dir).

Usage

Establishing Lua Context

using namespace sel;
State state; // creates a Lua context
State state{true}; // creates a Lua context and loads standard Lua libraries

When a sel::State object goes out of scope, the Lua context is automatically destroyed in addition to all objects associated with it (including C++ objects).

Accessing elements

-- test.lua
foo = 4
bar = {}
bar[3] = "hi"
bar["key"] = "there"
sel::State state;
state.Load("/path/to/test.lua");
assert(state["foo"] == 4);
assert(state["bar"][3] == "hi");
assert(state["bar"]["key"] == "there");

When the [] operator is invoked on a sel::State object, a sel::Selector object is returned. The Selector is type castable to all the basic types that Lua can return.

If you access the same element frequently, it is recommended that you cache the selector for fast access later like so:

auto bar3 = state["bar"][3]; // bar3 has type sel::Selector
bar3 = 4;
bar3 = 6;
std::cout << int(bar3) << std::endl;

Calling Lua functions from C++

-- test.lua

function foo()
end

function add(a, b)
  return a + b
end

function sum_and_difference(a, b)
  return (a+b), (a-b);
end

function bar()
  return 4, true, "hi"
end

mytable = {}
function mytable.foo()
    return 4
end
sel::State state;
state.Load("/path/to/test.lua");

// Call function with no arguments or returns
state["foo"]();

// Call function with two arguments that returns an int
// The type parameter can be one of int, lua_Number, std::string,
// bool, or unsigned int
int result = state["add"](5, 2);
assert(result == 7);


// Call function that returns multiple values
int sum, difference;
sel::tie(sum, difference) = state["sum_and_difference"](3, 1);
assert(sum == 4 && difference == 2);

// Call function in table
result = state["mytable"]["foo"]();
assert(result == 4);

Note that multi-value returns must have sel::tie on the LHS and not std::tie. This will create a sel::Tuple as opposed to an std::tuple which has the operator= implemented for the selector type.

Calling Free-standing C++ functions from Lua

int my_multiply(int a, int b) {
    return (a*b);
}

sel::State state;

// Register the function to the Lua global "c_multiply"
state["c_multiply"] = &my_multiply;

// Now we can call it (we can also call it from within lua)
int result = state["c_multiply"](5, 2);
assert(result == 10);

You can also register functor objects, lambdas, and any fully qualified std::function. See test/interop_tests.h for details.

Accepting Lua functions as Arguments

To retrieve a Lua function as a callable object in C++, you can use the sel::function type like so:

-- test.lua

function add(a, b)
    return a+b
end

function pass_add(x, y)
    take_fun_arg(add, x, y)
end
int take_fun_arg(sel::function<int(int, int)> fun, int a, int b) {
    return fun(a, b);
}

sel::State state;
state["take_fun_arg"] = &take_fun_arg;
state.Load("test.lua");
assert(state["pass_add"](3, 5) == 8)

The sel::function type is pretty much identical to the std::function type excepts it holds a shared_ptr to a Lua reference. Once all instances of a particular sel::function go out of scope, the Lua reference will automatically become unbound. Simply copying and retaining an instance of a sel::function will allow it to be callable later. You can also return a sel::function which will then be callable in C++ or Lua.

Running arbitrary code

sel::State state;
state("x = 5");

After running this snippet, x will have value 5 in the Lua runtime. Snippets run in this way cannot return anything to the caller at this time.

Registering Classes

struct Bar {
    int x;
    Bar(int x_) : x(x_) {}
    int AddThis(int y) { return x + y; }
};

sel::State state;
state["Bar"].SetClass<Bar, int>("add_this", &Bar::AddThis);
bar = Bar.new(5)
-- bar now refers to a new instance of Bar with its member x set to 5

x = bar:add_this(2)
-- x is now 7

bar = nil
--[[ the bar object will be destroyed the next time a garbage
     collection is run ]]--

The signature of the SetClass template method looks like the following:

template <typename T, typename... CtorArgs, typename... Funs>
void Selector::SetClass(Funs... funs);

The template parameters supplied explicitly are first T, the class you wish to register followed by CtorArgs..., the types that are accepted by the class's constructor. In addition to primitive types, you may also pass pointers or references to other types that have been or will be registered. Note that constructor overloading is not supported at this time. The arguments to the SetClass function are a list of member functions you wish to register (callable from Lua). The format is [function name, function pointer, ...].

After a class is registered, C++ functions and methods can return pointers or references to Lua, and the class metatable will be assigned correctly.

Registering Class Member Variables

For convenience, if you pass a pointer to a member instead of a member function, Selene will automatically generate a setter and getter for the member. The getter name is just the name of the member variable you supply and the setter has "set_" prepended to that name.

// Define Bar as above
sel::State state;
state["Bar"].SetClass<Bar, int>("x", &Bar::x);
-- now we can do the following:
bar = Bar.new(4)

print(bar:x()) -- will print '4'

bar:set_x(-4)
print(bar:x()) -- will print '-4'

Member variables registered in this way which are declared const will not have a setter generated for them.

Registering Object Instances

You can also register an explicit object which was instantiated from C++. However, this object cannot be inherited from and you are in charge of the object's lifetime.

struct Foo {
    int x;
    Foo(int x_) : x(x_) {}

    int DoubleAdd(int y) { return 2 * (x + y); }
    void SetX(int x_) { x = x_; }
};

sel::State state;

// Instantiate a foo object with x initially set to 2
Foo foo(2);

// Binds the C++ instance foo to a table also called foo in Lua along
// with the DoubleAdd method and variable x. Binding a member variable
// will create a getter and setter as illustrated below.
// The user is not required to bind all members
state["foo"].SetObj(foo,
                    "double_add", &Foo::DoubleAdd,
                    "x", &Foo::x);

assert(state["foo"]["x"]() == 2);

state["foo"]["set_x"](4);
assert(foo.x == 4);

int result = state["foo"]["double_add"](3);
assert(result == 14);

In the above example, the functions foo.double_add and foo.set_x will also be accessible from within Lua after registration occurs. As with class member variables, object instance variables which are const will not have a setter generated for them.

Writeups

You can read more about this project in the three blogposts that describes it:

There have been syntax changes in library usage but the underlying concepts of variadic template use and generics is the same.

Roadmap

The following features are planned, although nothing is guaranteed:

  • Smarter Lua module loading
  • Hooks for module reloading
  • VS support

selene's People

Contributors

adam4813 avatar amorozov avatar anonymousprogrammerlandau avatar anthraxx avatar belak avatar bitdeli-chef avatar dabbertorres avatar drmgc avatar gczuczy avatar guilhembernard avatar hbccdf avatar ioannis-e avatar jeremyong avatar kamelusz avatar peterth avatar reinkim avatar saluev avatar satoren avatar slobodin avatar taronyu avatar zaruofiron avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

selene's Issues

Class Registering and References

Attempting to construct a registered class in a Lua script causes a segmentation fault.
(Tested on most recent git version and back to v0.3)

Here's a reproducible example:
main.cpp

#include <iostream>
#include <string>
#include <Selene/selene.h>

class Bar
{
    public:
        Bar(std::string& w)
        {
            word = w;
        }

        ~Bar() {}

        void say()
        {
            std::cout << word << "\n";
        }

    private:
        std::string word;
};

int main()
{
    sel::State luaState{true};

    luaState["Bar"].SetClass<Bar, std::string&>("say", &Bar::say);

    luaState.Load("test.lua");

    return 0;
}

test.lua:

bar = Bar.new("hello world")

bar:say()

Get rid of the references and no seg fault occurs.

It's not just std::string&'s either, an int& causes the same behavior.

Error in Readme.md

Hi,

I think there's an error in the documentation provided in the readme file.
In the section "Registering class member variables", in the lua example of setting and getting "x". You don't use the " : " to access the methods, but a point ( " . " ). It sould be :

-- now we can do the following:
bar = Bar.new(4)

print(bar:x()) -- will print '4'

bar:set_x(-4)
print(bar:x()) -- will print '-4'

since set_x() and x() are methods of the object Bar

Examples of usages with different C++ datatypes

Lua newbie here, trying to use this with a simple C++ test project, evaluating use for a bigger project.
Would be useful to have examples of all the datatypes available in Selene.
Sorry if I'm not understanding something, but is there a way to use Selene to pass array (std::array) or raw array [] to lua somehow easily ?

Or do I have to push it to the stack somehow one value at a time ?
How about std::vector ?

Thanks, this looks good!

Memory leak upon calling functions from multiple states!

In a game that I'm working I need every controllable object to have it's own state that controls only that object. And scripts of that object can have functions that respond to events (usually every frame or key etc.) I tried to simulate this kind of behavior and see how it works, however, after I create about 10000 states (just for benchmarking reasons since I won't have this many the actual game) in an std::vector, the memory settles to about 160~ Mb. When I get to call a function from every state in that vector, the memory usage increases uncontrollably and doesn't free the memory until the application is shut down.

Lua script used:

function event(a, b)
    return some_func(a + b);
end

C++ code used:

#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <vector>
#include <assert.h>

#include <selene.h>

bool some_func(int val)
{
    return static_cast<bool>(val);
}

clock_t time_start = clock();
void counter(bool toggle = false)
{
    if (toggle)
    {
        time_start = clock();
        printf ("<< Starting at to count from %d.\n", time_start);
    } else {
         clock_t time_passed = clock() - time_start;
         printf (">> It took me %d ticks (%f seconds).\n", time_passed ,((float)time_passed) / CLOCKS_PER_SEC);
    }
}

int main(int argc, char **argv)
{
    std::vector< sel::State* > states;
    states.reserve(10001);

    sel::State* st = nullptr;

    // Create a large number of states
    for (int i = 0; i < 10000; i++)
    {
        st = new sel::State(true);
        (*st)["some_func"] = &some_func;
        (*st)["counter"] = &counter;
        st->Load("script.lua");
        states.push_back(st);
    }

    // PAUSE
    char str[32];
    printf("Check memory usage before function call benchmark.");
    scanf("%s", str);

    // Call the event function inside every state 10000 times
    for (int i = 0; i < 10000; i++)
    {

        counter(true);

        for (auto itr = states.begin(); itr != states.end(); ++itr)
        {
            bool result = (*(*itr))["event"](10, 3);
            assert(result == true);
        }

        counter(false);

    }

    // PAUSE
    printf("Check memory usage after function call benchmark.");
    scanf("%s", str);

    // Close the states
    for (auto itr = states.begin(); itr != states.end(); ++itr)
    {
        delete *itr;
    }
    states.clear();


    return EXIT_SUCCESS;
}

I'm not an expert programmer and I might have done something wrong that I haven't noticed! However I'm curious what is causing the memory leak.

Software Version
Lua 5.2.3
MinGW GCC 4.8.1
CodeBlocks 13.12

Compiling on OS X

I had an issue compiling on Mavericks. Couldn't find lua.h. I added include_directories(/usr/local/include) to the CMake file and that seemed to fix it.

Add exception support

Add exceptions to the sel namespace to handle a number of edge cases (stack overflow, incorrect type, etc).

Compilation with VisualStudio 2013

We tried to make Selene compile with VisualStudio. We got it to a state where all compiler messages seemed to be fixed but sadly cl.exe just crashes at the Tuple::operator= and Selector::SetClass methods (if all usages of the tuple operator= were removed).
Maybe these methods could be expressed in a way that is compatible to VisualStudio?

diff:
https://github.com/voxelinc/Selene/compare/jeremyong:master...master
crash:
https://gist.github.com/xchrdw/6bd001e84305f615cbb1

I also tried the Visual C++ Compiler November 2013 CTP which supports more C++11 features but still crashes at these lines.

Can't register constant member functions

It's not possible to register constant member functions when registering a class.

Minimal example code:

class C {
public:
   bool get() const;
}
bool C::get() const {return true;}

//…
sel::State state;
state["C“].SetClass<C>("get", &C::get);

The above case yields Semantic Issue: Function cannot return function type 'bool () const' in sel::Class:_register_member() when compiling with a
recent version of Clang. The code however compiles when the const keyword is
removed.

Allow for creating setters for object instances

When an object is registered, (with SetClass) it can automagically make getters and setters.
With instances, (with SetObj) this doesn't happen.
If it's possible to create the getters and setters with the object instance, I think that would be a time-saving addition.

Add Class registration

Currently, one can use Selene to register object instances in Lua. It'd also be good to construct C++ objects within Lua.

To do this, we need to implement sel::State::AddClass providing a list of constructors available, and methods. In addition, we must ensure that if the Lua object is garbage collected, the object must be destroyed. This will be done with the __gc metamethod. The C++ object itself will be retained by State so if the Lua context goes away,so will the object.

Add support for enum class

It would be convenient to have enum class support similar to how classes are implemented.

enum class EnumClass {
    Hesiod = 0,
    Theia = 1
};

state["EnumClass"].SetEnumClass<EnumClass>(
    "Hesiod", EnumClass::Hesiod, 
    "Theia", EnumClass::Theia);
--lua.lua
var = EnumClass.new("Hesiod")
someFunction(var) -- some function with an EnumClass parameter

Metatables not assigned to custom return types.

It seems custom userdata returned by a function is still not quite working, the metatable does not get assigned correctly.

Example:
main.cpp

#include <Selene/selene.h>
#include <iostream>
#include <vector>

struct A
{
    A(int x)
    {
        this->x = x;
    }

    int x;
};

std::vector<A> as;

int main()
{
    sel::State lua{true};

    lua["A"].SetClass<A, int>("x", &A::x);

    lua["makeA"] = [&](int x) -> A&
    {
        as.push_back({x});
        auto it = as.end();
        it--;
        return *it;
    };

    if(!lua.Load("main.lua"))
        std::cout << "Could not load script\n";

    return 0;
}

main.lua:

a = makeA(3)

A = A.new(4)

print(getmetatable(a))
print(getmetatable(A))

Output:

nil
table: 0xec1690

If I add a "print(a:x())", the script is unable to be run.

Make Selene header only

There is very little source code that actually gets compiled into the library due to the amount of templatized functionality. Make it a header only library would make it significantly easier to integrate into existing code.

Any chance of float being supported as well?

Title says it all, I'm unable to use float data types as class member variables.

If there is a technical reason behind this, and it would be too difficult, I understand if not, it'd just be nice!

Unsupported types : short and long (unsigned) int

Hello,
I found a "bug" when trying to register methods/functions with long unsigned int as parameters.
I'm not very familiar with templates, but after a quick research in your code, I solved the problem by overloading "_check_get" and "_push" for long unsigned int aka size_t for me.

here is my code :
inline unsigned int _check_get(_id<size_t>, lua_State *l, const int index) { return luaL_checkunsigned(l, index); }
and
inline void _push(lua_State *l, size_t u) { _push(l, (unsigned int) u); }

I know the problem is the same for long int, short int, short unsigned int etc...

As i'm not very familiar with your code, I preferred to post it as an issue rather than making a pull request, maybe you would have a better way to solve it.

Thank you for your work on this great binding !

Lua-function called from c++ fires twice in debug-mode

Hey there,

i had a little problem, my lua-function fired twice when i compiled in debug-mode (visual studio express 2013). Code to reproduce:

function ltest()
    print("Hello World");
end
    sel::State state{ true };
    state.Load("test.lua");
    auto ltest = state["ltest"];
    ltest();

I figured out, that "named return type optimisation" won't work in debug-mode and since Selector has no move-construktor, it will use the copy-constructor to pass the 'copy' out of the operator(). I fixed this by just creating a small move-constructor for Selector, but since i'm still a beginner in c++ i'm not sure if its the best approach and i don't even know if there is a reason why Selector has no move-constructor so i hope you'll decide what to do with this issue.

Segmentation fault using none Selene created lua_State

Given the following code:
lua_State* vm = luaL_newstate();
luaL_openlibs(vm);
{
sel::State sel_state(vm);
open_Selene_set_n_get(sel_state);//registers a class type with functions
run_compare(vm,"mfunc","Selene");//runs a Lua file which creates a C++ type and calls a function on it
// sel_state.ForceGC();
}
lua_gc(vm, LUA_GCCOLLECT, 0);
lua_close(vm);

When the ForceGC is commented out it can cause a segmentation fault as the gc may not have ran, yet there can be a Selene created class waiting to be collected. The library is storing dynamically allocated pointers for the __gc method, however when the State destructor has been called the pointers stored are now dangling. This results in a segmentation fault.

Personally I feel the destructor for the State must call the garbage collector when the state is none NULL. The example in the readme is for a Selene created state but does say "When a sel::State object goes out of scope, the Lua context is automatically destroyed[not valid here] in addition to all objects associated with it (including C++ objects)."

Allow building of a static library

With CMake if you don't specify SHARED in the add_library target, it allows for users to specify the type of library built with -DBUILD_SHARED_LIBS.

option(BUILD_SHARED_LIBS "Build shared libraries." ON)

This line should let you still build shared libs by default, but still let users switch to static if they want.

Add support for `sel::Selector`

Right now, the API can only bind things to globals or fields of a table (one level). Much better would be a reference object that the user can use to traverse tables in Lua that can be chained together.

Existing functions like Call and Register would be overloaded to either take a string (bound to a global), or a sel::Selector which could point to an arbitrarily nested table element in Lua.

Can't register methods with custom return type

Hello,

I believe this issue follows issue #34. I tried to register methods from a class with custom types. As long as custom types are parameters, it's OK, but when it's a return type, it won't work.
Here is a sample of code for demonstration :

struct A { //a stupid simple struct
    A(int val):x(val){}
    int x;
};

class B { //a stupid simple class with a lonely A member
public:
    B():obj(A(0)){}
    A& getobj(A& obj) {return obj;}
    void setobj(A& val) {obj=val;}
private:
    A obj;
};

int main()
{
sel::State state{true};
state["A"].SetClass<A,int>();
state["B"].SetClass<B>("setobj", &B::setobj); //here it works
state["B"].SetClass<B>("getobj", &B::getobj); //here stops the compilation
}

as I saw issue #34 I tried adding custom parameters, but I won't change a thing.
By the way, I also tried functions with custom return types and parameters, and everything works fine. I believe issue #34 is fixed ?

Sorry for the long post. As I'm not familiar with templates, I can only give you as much information as I can on what works and what doesn't. Hope it will be easy to handle and thank you !

Use lua_Number typedef for number types

Don't have float or double _get/_push functions; just have lua_Number

Lua can be built with various number types. Avoid accidental loss of precision or too much precision by using the type lua headers give you.

Can't register float's in classes.

state["Foo"].SetClass(
"floatx", &Foo::floatx);

where floatx is a float, throws the following error in clang:

Selene/include/selene/BaseFun.h:36:29: error: no matching function for call to
'_check_get'
return std::tuple<T...>{_check_get(_id{}, state, N + 1)...};
...

Lua 5.1 support

I see you're using some 5.2 features (LUA_OK, lua_tounsigned, luaL_checkunsigned). Would be nice to be able to use it with 5.1. If not, you should specify what version you support. Thanks.

Can't distinguish between nil variables (that don't exist) and default values

It seems unclear to me as to how to deal with variables that do not exist in the lua state. This combined with issue #41 means that lots of things can go bad without the user being informed. I think the correct behaviour here would be an exception, as int cannot be NULL. However it has been noted in #10 that exceptions are not going to be used so I am not sure how to proceed.

$ lua
Lua 5.2.3  Copyright (C) 1994-2013 Lua.org, PUC-Rio
> print(y)
nil
>

#include "Selene/include/selene.h"
#include <string>
#include <iostream>

int main(void) {
    sel::State state;
    state["x"] = 0;
    state["y"] = std::string("");

    int x = state["x"];
    int x2 = state["x2"]; // this doesn't exist

    std::string y = state["y"];
    std::string y2 = state["y2"]; // this doesn't exist

    std::cout << (x == x2 ? "same" : "different") << std::endl;
    std::cout << (y == y2 ? "same" : "different") << std::endl;
    return 0;
}
$ g++-4.9 -std=c++11 -g -I/usr/include/lua5.2 test.cpp -llua5.2 -o test
$ ./test
same
same
$

Selectors and lambdas

Currently if one wants to use selectors with lambdas the syntax is quite cumbersome:

sel:State L;
// This would be nice but does not work:
L["myfun"] = [](int i) { return 2*i; };
// Instead this is required:
L["myfun"] = std::function<int(int)>([](int i) { return 2*i; });

This is because the operator= from selector wants a std::function and rejects lambdas. A more permissive template would be very nice.

Pass additional data to class constructors

This one is a slightly odd request, but I'm using this as a map format and I'd like to be able to make map elements and register them with a map.

One way I can think of doing this is to pass a reference to the map to the map element as it's being created.
Another way would be to allow the functions to look at data in the State and read from a global map there.

If you have a better way of accomplishing this, it would be appreciated, but I think the simplest (at least from my naive perspective) would be to pass extra data to the constructor of the objects.

Current state of Visual Studio support

I already tried to make selene run with Visual Studio about half a year ago and it failed because of some compiler bugs (#22).
I just got a response from MS that they solved this specific problem in Visual Studio 2013 Update 3 and tried it again. (http://connect.microsoft.com/VisualStudio/feedbackdetail/view/826262/cl-exe-crashes-on-extensive-template-use)
MS still doesn't support some features but it seems possible to work without them. (no constexpr, rvalue refs, ...). Two tests fail, one with an error in lua (calling null) the other when comparing the returned tuple of a multireturn function call with the expected result. I didn't further look into them.
https://github.com/xchrdw/Selene/compare/vs2013_3

After this I tried the same with Visual Studio 2014 CTP and it looks like Microsoft finally implemented the most important things. Only initializer lists in constructors are missing and all tests succeed :)
https://github.com/xchrdw/Selene/compare/vs2014_ctp

I can just leave these branches here or create a PR for the VS2014 branch if you're interested in it.

nullptr == nil

I think this would be a nice feature. If a user function returns a nullptr, to have Lua push a nil. Otherwise, there isn't much room for error handling of sorts.

If you're a fan of the idea, I'll make the change(s) myself, I just don't know the codebase all that well.

Can't register function with custom return type & primitive parameters

It's apparently not possible register a free-standing function with custom return type and primitive parameters.

Mat4x4 *perspective(float fovy, float aspect, float zNear, float zFar) {
    return new Mat4x4();
}

state["Mat4x4"].SetClass<Mat4x4>();
state["perspective"] = &perspective; // this results in an error: 
    // "No matching function for call to '_check_get' in BaseFun.h"

However, registering a similar function with custom type references as parameters (e.g. Mat4x4 *perspective(Mat4x4 &param) {} does not result in an error. I guess an overload is missing somewhere?

Multiple Definition of _push

g++ 4.8.1 throws a "multiple definition" error for the _push functions in primitives.h (starting at line 205).
Making all of them inline seems to fix this.

It also throws it for _lua_dispatcher at line 15 in BaseFun.h
Making it inline fixes it as well.

passing std::string ref from lua to c++ function

I'm calling a c++ class member function from lua that has a std::string& argument. Once called an empty string is passed in. The correct string is passed in if I change the function's argument to accept std::string rather than std::string&. Is there any way around this by registering std::string somehow?

Can't bind to std::vector member functions in any obvious way

Hi,

Please forgive me if this is the wrong place to ask, I could not find anywhere else that seemed appropriate.

I'm trying to bind the push_back method of an std::vector into a lua object, but it doesn't seem to be working, and I'm a bit lost trying to decipher the c++ template errors. My test code is like this:

  sel::State state;
  std::vector<int> test_vector(5, 1);

  state["vec"].SetObj(test_vector, 
    "push_back", 
    &std::vector<int>::push_back
  );

And the numerous compiler errors I get are: https://gist.github.com/jeremyherbert/f09e1e4f93a11e3802a3

The selene examples on the readme work perfectly. I'm using Ubuntu 14.04 with gcc 4.8.2:

Using built-in specs.
COLLECT_GCC=/usr/bin/gcc
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)

Any hints or tips would be greatly appreciated.

Allow creation of tables

Right now, this will fail:

sel::State state;
state["meta"]["data"] = 42;
state.Load("something.lua");

The workaround is as follows, but it would be nice to have something like this built in:

base.lua:

meta = {}
sel::State state;
state.Load("base.lua");
state["meta"]["data"] = 42;
state.Load("something.lua");

Error compiling with MinGW

If I try to compile a program that so much as includes selene.h, my compiler will complain about issues in Selector.h:
'''
C:\Selene\include\selene\Selector.h:291: error: expected ';' at end of member declaration
Selector&& operator[](const char *name) && {
^
'''

And here is the offending block:
'''c++
Selector&& operator[](const char *name) && {
_name += std::string(".") + name;
_check_create_table();
_traversal.push_back(_get);
_get = this, name {
lua_getfield(_state, -1, name);
};
_put = [this, name](Fun fun) {
fun();
lua_setfield(_state, -2, name);
lua_pop(_state, 1);
};
return std::move(*this);
}
'''

I am using MinGW 4.8.0 32-bit by MinGW-builds provided with Qt Creator on Windows 7 64-bit. I am compiling with these flags: -std=c++11 -Wall -Wextra -pedantic -Wno-unused-local-typedefs -Wno-unused-parameter

Error handling

Can some documentation be added regarding error handling in Selene? For example, calling a function that does not exist in the lua State causes a panic and abort. Is there any way to directly access the low level Lua state object errors?

Selector caching with functions

Hey there,

i have some troubles caching a Selector which represents a lua-function.

This is my lua-function:

function ctest(text)
    print("Text von C: " .. text);
end

And calling with this code works as expected:

state["ctest"]("What the hell...");

But none of them does anything:

    sel::Selector f1 = state["ctest"];
    f1("Test 1");
    sel::Selector* f2 = &state["ctest"];
    (*f2)("Test2");

Edit: Actually, this works but unexpected:

    auto f1 = state["ctest"];
    f1("Test 1");
    system("pause");

The console-output:

Drücken Sie eine beliebige Taste . . .
Text von C: Test 1

I guess the problem is that the function gets not called directly but in Selectors destructor. Why?

Stack creep

Because of a lack of test coverage in this area, a number of operations cause a memory leak to the stack.

User Type Converters

Extending the current primitive operations (get, push, check) for user types could be pretty useful since it'd allow passing objects around without requiring registration. Instead of providing registration data, the user could instead specialize a template struct (for example) which would contain get, push and check methods for the user's type, essentially providing a direct translation to Lua types.

A possible use case would be enums and mathematical vectors.

Add suport to abstract class

I'm trying to add some abstract classes Ogre3D library, but without success.

It would be good to have support for this.

Ogre3D have some abstract classes, like Ogre::SceneManager, and we create a instance using Ogre::Root::createSceneManager and return a scene managers like Octree, BSP or Generic.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.