Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating new classes/members at run-time in scripting languages used in C++ [closed]

I've been working on this problem off and on for a few months, and now wanted to really come up with a proper solution that will handle the case of creating new user-defined classes (and instances of those classes) with member functions/properties at run-time in a C++11 project.

So far, I've been using SWIG (formerly with Python, now with Lua, exploring Squirrel). Like all the C++ binding/embedding libraries I've encountered so far (Luna*, luabinder, luabind, OOLua, Sqrat/Sqext, Squall), all expect your classes to be predefined in C++ prior to code execution because they either rely on preprocessor directives or templates.

So my question is, are there any libraries out there that use a more procedural approach to wrapping a language, or are there any good tutorials/examples for something like Lua or Squirrel, that one would recommend for handling the creation of custom-named classes with custom members and functions? Some direction would be greatly appreciated.

Even simply a good example showing how to create a custom class with a function and a property, in either Lua, Squirrel, via their respective C++ APIs without the use of macros/templates/dynamically-generated code, would be hugely helpful.

EDIT: I have gone as far as creating an Instance class that contains a std::vector of members key/value pairs, and a member identifying the type so functions can be looked up. However, there is very little documentation out there on creating simple classes in Lua/Squirrel without the use of static code.

EDIT 2: I would like a solution that works on any platform and without having to dynamically link.

like image 792
Mike Weir Avatar asked Oct 30 '22 17:10

Mike Weir


1 Answers

Creating a class derived from some existing C++ class is the only way (known to me) to bring a new class into a running C++ program. Short of dynamically compiling actual C++ source and loading the resulting library, there is no way to physically add a new class. The next best thing is to create a proxy object in C++ that wraps a Python (Lua etc) object, and make that Python (Lua) object an instance of a class that extends an existing C++ class mirrored to the Python (Lua) side.

        C++

     +---------+         mirrors                   +--------------+
     | class X |  ...............................> | class X      |
     +---------+                                   | mirrored to  |
          |                                        | Python       |
          | inherits                               +--------------+
          v                                      inherits  |
     +-----------------+                                   v
     | class X_Wrapper |        references         +--------------+
     |    | python obj ------------------------->  | class CX(X): |
     +-----------------+                           |    def met() |
                                                   +--------------+

Here's an example of extending a C++ class with Python, using boost::python as a bridge.

C++ side:

#include <boost/python.hpp>
#include <iostream>

using namespace boost::python;
// this is the interface we will implement in Python
struct World
{
    virtual std::string greet() = 0;
    virtual ~World() {}
};

// this is a helper class needed to access Python-overrided methods
struct WorldWrap : World, wrapper<World>
{
    std::string greet()
    {
        return this->get_override("greet")();
    }
};

// This function tests our class implemented in Python
std::string test(World* w)
{
    std::cout << "Calling w->greet() on some World-derived object\n";
    return w->greet();
}

// This is what the Python side will see
BOOST_PYTHON_MODULE(hello)
{
    class_<WorldWrap, boost::noncopyable>("World")
            .def("greet", pure_virtual(&World::greet));

    def("test", test);
}

Python side:

import hello


class HomeWorld(hello.World):
    """ Implements a function defined in C++ as pure virtual """
    def greet(self):
        return "howdy"

home = HomeWorld()
print (hello.test(home))
like image 173
n. 1.8e9-where's-my-share m. Avatar answered Nov 15 '22 04:11

n. 1.8e9-where's-my-share m.