【问题标题】:Calling C++ class functions from Ruby/Python从 Ruby/Python 调用 C++ 类函数
【发布时间】:2015-06-02 16:54:32
【问题描述】:

在我的特定情况下,我有一个复杂的类(一类类的类),我想向脚本语言(又名 Ruby)公开。不是直接传递那个复杂的类,而是有人给了我一个想法,就是将一些函数开放给像 Ruby 这样的脚本语言,这看起来更简单。我见过 Rice,但我见过的唯一例子是使用简单的函数来乘法,而不是与类交互。

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

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

还有:

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

回答:

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

编辑:

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

【问题讨论】:

  • 经过一些研究,我发现 Ruby 可能不是嵌入 C++ 的最佳语言。如果是这样,我可以更改问题,以便脚本语言是 Python,如果它更有意义并且不会使任何答案无效
  • 所以你可以在问题中添加python标签来引起特别的注意。
  • @hedgesky 谢谢你的提醒,我完全忘记了这个问题,直到 Orfby 提出赏金。

标签: python c++ ruby embedding


【解决方案1】:

您可以使用cythonBoost.Python 从python 调用本机代码。由于您使用的是 c++,我建议您查看Boost.Python,它提供了一种非常自然的方式为 python 包装 c++ 类。

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

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

【讨论】:

  • 这很完美,但有一件事,我将如何为普通函数而不是类函数执行此操作?
  • 在一个示例中进行了编辑。 Boost.Python 真的很棒,我建议你查看这个 wiki 了解更多信息:wiki.python.org/moin/boost.python
【解决方案2】:

Boost.Python 呢?

你为什么不想使用 SWIG?

【讨论】:

  • 我对 SWIG 没有任何意见,我只是说我不想要“这里是 X 下载/文档页面,祝你好运!”的答案。我想要“这是 X 库/工具,这是您公开给定源代码的方式,这是访问 Foo::pushBack(const int&amp; newInt) 的一些示例 Python/Ruby 代码”。 (关于 Boost.Python)我尝试过使用 Boost 库,但我永远无法使用需要构建的库(如 Python 库)。
  • @bboy3577 我明白了。好吧,我从来没有使用过 Boost.Python,而且多年来我也没有使用过 SWIG,所以我只能提供文档中的示例。 Boost.Python 文档有一些很好的例子。 jornb87 发布的答案有一些代码示例。
  • @bboy3577 另外,当你说:我不想要“这里是 X 下载/文档页面,祝你好运!”的答案时。我想要“这是 X 库/工具,这是您公开给定源代码的方式,这是一些访问 Foo::pushBack(const int& newInt) 的示例 Python/Ruby 代码” 似乎您希望其他人这样做为你工作。如果您展示您在 SWIG/Boost.Python 中尝试过的内容以及您遇到的错误以及您尝试修复的内容,那么人们会更有利于帮助您。
猜你喜欢
  • 1970-01-01
  • 2013-08-30
  • 2011-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-02
  • 2016-03-25
相关资源
最近更新 更多