6

In my specific circumstance, I have a complex class (a class of classes of classes) that I want to expose to a scripting language (aka Ruby). Rather that directly pass that complex class, someone gave me the idea of just opening up a few functions to a scripting language like Ruby, which seemed simpler. I've seen Rice but the only examples I've seen use simple functions that just multiply something, rather than interfacing with a class.

For simplicity, I have a simple class with functions I want to expose:

class Foo
{
    private:
        //Integer Vector:
        std::vector<int> fooVector;

    public:
        //Functions to expose to Ruby:
        void pushBack(const int& newInt) {fooVector.push_back(newInt);}
        int& getInt(const int& element) {return fooVector.at(element);}
};

ALSO:

I'd prefer not to just have a link to the download page of SWIG, or an article explaining how to do this with rice that was written in 2010, I would like a guide that will likely work (I haven't had much luck just yet)

ASWELL:

I'm using Linux (Ubuntu) but this is a cross-compatible program, so I must be able to compile on Windows and OS X

EDIT:

I do understand that shared libraries exist (dll and so files), but I don't know if I can have a library that depends on a .hpp file containing the class(es).

bboy3577
  • 417
  • 5
  • 14
  • After some research, I've seen that Ruby might not be the best language for embedding with C++. If so, I can change the question so the scripting language is Python, if it makes more sense and wouldn't invalidate any answers – bboy3577 Jun 02 '15 at 19:44
  • So you can add `python` tag to question to attract specific attention. – hedgesky Jun 22 '15 at 21:29
  • @hedgesky Thanks for reminding me, I completely forgot about this question until Orfby put up a bounty. – bboy3577 Jun 22 '15 at 21:41

2 Answers2

2

You can use cython or Boost.Python to call native code from python. Since you are using c++, i'd recommend looking into Boost.Python which offers a very natural way of wrapping c++ classes for python.

As an example (close to what you provided), consider the following class definitions

class Bar
{
private:
    int value;

public:
    Bar() : value(42){ }

    //Functions to expose to Python:
    int getValue() const { return value; }
    void setValue(int newValue) { value = newValue; }
};

class Foo
{
private:
    //Integer Vector:
    std::vector<int> fooVector;
    Bar bar;

public:
    //Functions to expose to Python:
    void pushBack(const int& newInt) { fooVector.push_back(newInt); }
    int getInt(const int& element) { return fooVector.at(element); }
    Bar& getBar() { return bar; }
};

double compute() { return 18.3; }

This can be wrapped to python using Boost.Python

#include <boost/python.hpp>
BOOST_PYTHON_MODULE(MyLibrary) {
    using namespace boost::python;

    class_<Foo>("Foo", init<>())
        .def("pushBack", &Foo::pushBack, (arg("newInt")))
        .def("getInt", &Foo::getInt, (arg("element")))
        .def("getBar", &Foo::getBar, return_value_policy<reference_existing_object>())
    ;

    class_<Bar>("Bar", init<>())
        .def("getValue", &Bar::getValue)
        .def("setValue", &Bar::setValue, (arg("newValue")))
    ;

    def("compute", compute);
}

This code can be compiled to a static library MyLibrary.pyd and used like this

import MyLibrary

foo = MyLibrary.Foo()
foo.pushBack(10);
foo.pushBack(20);
foo.pushBack(30);
print(foo.getInt(0)) # 10
print(foo.getInt(1)) # 20
print(foo.getInt(2)) # 30

bar = foo.getBar()
print(bar.getValue()) # 42
bar.setValue(17)
print(foo.getBar().getValue()) #17

print(MyLibrary.compute()) # 18.3
jornb87
  • 1,441
  • 10
  • 15
  • This is perfect, but one thing, how would I do this for a normal function instead of a class function? – bboy3577 Jun 23 '15 at 15:11
  • Edited in an example of that. Boost.Python is really great, I'd recommend you check out this wiki for more info: https://wiki.python.org/moin/boost.python – jornb87 Jun 23 '15 at 15:19
0

What about Boost.Python?

How come you don't want to use SWIG?

Community
  • 1
  • 1
Di Zou
  • 4,469
  • 13
  • 59
  • 88
  • I have nothing against SWIG, I just said I don't want an answer that is "Here's X Download/Documentation page, good luck!" I want "Here's X library/tool, this is how you expose the given source code, and this is some example Python/Ruby code that accesses `Foo::pushBack(const int& newInt)`". (About Boost.Python) I've tried using the Boost libraries but I can never use the libraries that need building (like the Python libraries). – bboy3577 Jun 23 '15 at 15:08
  • @bboy3577 I see. Well I've never used Boost.Python and I haven't used SWIG in years so I can't provide anything more than the examples in the documentation. The Boost.Python documentation has some good examples. The answer posted by jornb87 has some code examples. – Di Zou Jun 23 '15 at 15:11
  • @bboy3577 Also, when you say: I don't want an answer that is "Here's X Download/Documentation page, good luck!" I want "Here's X library/tool, this is how you expose the given source code, and this is some example Python/Ruby code that accesses Foo::pushBack(const int& newInt)" It just seems like you want other people to do work for you. It's a lot more conducive for people to help you if you show what you've attempted in SWIG/Boost.Python and the error your having and what you've tried to fix it. – Di Zou Jun 23 '15 at 15:16