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).

3
  • 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 Commented Jun 2, 2015 at 19:44
  • So you can add python tag to question to attract specific attention. Commented Jun 22, 2015 at 21:29
  • @hedgesky Thanks for reminding me, I completely forgot about this question until Orfby put up a bounty. Commented Jun 22, 2015 at 21:41

2 Answers 2

2
+50

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
Sign up to request clarification or add additional context in comments.

2 Comments

This is perfect, but one thing, how would I do this for a normal function instead of a class function?
Edited in an example of that. Boost.Python is really great, I'd recommend you check out this wiki for more info: wiki.python.org/moin/boost.python
0

What about Boost.Python?

How come you don't want to use SWIG?

3 Comments

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 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.
@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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.