从 Ruby/Python 调用 C++ class 函数

Calling C++ class functions from Ruby/Python

在我的具体情况下,我有一个复杂的 class(一个 class of classes of classes)我想暴露给脚本语言(又名 Ruby)。而不是直接传递那个复杂的 class,有人给我的想法是只向 Ruby 这样的脚本语言开放一些函数,这看起来更简单。我见过赖斯,但我见过的唯一例子是使用简单的函数来乘以某些东西,而不是与 class.

接口

为简单起见,我有一个简单的 class,其中包含我想要公开的功能:

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);}
};

另外:

我不希望只有 link 到 SWIG 的下载页面,或者一篇 2010 年写的解释如何用大米做到这一点的文章,我想要一个可能会的指南工作(我还没有太多运气)

还有:

我正在使用 Linux (Ubuntu) 但这是一个交叉兼容的程序,所以我必须能够在 Windows 和 OS X 上编译

编辑:

我确实知道存在共享库(dll 和 so 文件),但我不知道我是否可以拥有一个依赖于包含 class(es) 的 .hpp 文件的库。

Boost.Python呢?

你怎么不想用 SWIG?

您可以使用 cython or Boost.Python to call native code from python. Since you are using c++, i'd recommend looking into Boost.Python,它提供了一种非常自然的方式来为 python.

包装 c++ classes

作为示例(接近您提供的内容),请考虑以下 class 定义

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; }

这可以使用 Boost.Python

换行到 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);
}

这段代码可以编译成静态库MyLibrary.pyd并像这样使用

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