【问题标题】:Calling c++ function, from Python script, on a Mac OSX在 Mac OSX 上从 Python 脚本调用 c++ 函数
【发布时间】:2013-08-22 22:42:16
【问题描述】:

我的 mac 上有一个 c++ 代码,它使用非标准库(在我的例子中是 OpenCV 库),需要对其进行编译,以便可以从其他计算机(至少从其他 mac 计算机)调用它。从 python 运行。所以我有 3 个基本问题:

  1. 如何编译我的项目以便可以从 python 中使用?我读了 我应该创建一个 *.so 文件,但该怎么做?
  2. 它应该像lib一样工作吗,所以python调用了一些特定的函数, 在 python 级别选择?
  3. 或者它是否应该包含一个 ma​​in 函数,该函数从 命令行?

关于如何做到这一点的任何想法? PS:我正在使用eclipse IDE编译我的c++项目。

干杯,

【问题讨论】:

  • 你考虑过 SWIG 接口生成器吗? swig.org IT 将 C/C++ 代码作为 .so 文件包装到 Python 代码中,您可以直接从 Py 调用这些 C/C++ 函数。

标签: c++ python c opencv compilation


【解决方案1】:

如何编译我的项目以便可以在 python 中使用?我读了 我应该创建一个 *.so 文件,但该怎么做?

这取决于您的编译器。以 g++ 为例: g++ -shared -o myLib.so myObject.o

它应该像lib一样工作吗,所以python调用了一些特定的函数, 在python级别选择?

是的,在我看来。这似乎是一种“显而易见”的方式,因为它非常适合 C++ 代码的模块化和演变。

【讨论】:

    【解决方案2】:

    如果您使用 linux,atmaere 和 nouney 的答案可能对您有用。

    就我而言,当我使用 MacOSX 时,我想出了使用 cython 库的方法。下面描述了一个简单明了的教程:

    如何从 Python 脚本调用 C++:

    1. 安装 CYTHON:要安装将 python 脚本与 c/c++ 集成的工具 Cython,请访问:https://pypi.python.org/pypi/Cython/

    2. 下载示例:从此处下载 C++ 实现示例:http://wiki.cython.org/WrappingCPlusPlus?action=AttachFile&do=get&target=cythoncpp.tgz

    3. 准备 C++ 源文件:确保您的 *.cpp 和 *.h 文件是正确的。在下载的示例中,文件名为 cpp_rect.h 和 cpp_rect.cpp

    4. CREATE PYTHON WRAPER CPLASS:根据下载示例中的 rectangle.pyx 文件或http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html?highlight=cpp#create-cython-wrapper-class中描述的模型

    5. 准备 SETUP.PY 文件:下载的示例已包含在此文件中,但可以在本教程中找到更多信息:http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html?highlight=cpp#specify-c-language-in-setup-py。 [PS: 1 最简单的编译方法是使用 disutilis 包,使用 setup.py 文件。有关编译选项的更多信息,请访问http://docs.cython.org/src/reference/compilation.html#

    6. 尝试编译:从源文件所在的同一文件夹转到终端。此时您已经拥有 4 个文件:cpp_rect.h、cpp_rect.cpp、rectangle.pyx 和 setup.py。从那里,执行命令$ python setup.py build_ext --inplace

    7. 如果您收到 g++ 错误,例如发生在我身上:“无法执行 gcc-4.2:没有这样的文件或目录”,您可以通过 sudo ln -s /usr/bin/gcc /usr/bin/gcc-4.2 破解标志系统。不如重复上一步。

    8. 测试您的代码:此时,您拥有所需的一切:setup.py 与 rectangle.pyx 一起用于生成 rectangle.so 文件,这正是我们所需要的!只需构建一个 pythons 脚本来测试您的集成。幸运的是,该示例已经包含一个名为 use_rect.py 的测试脚本。

    现在只需使用“$ python userect.py”从终端运行它

    【讨论】:

      【解决方案3】:

      这是一个使用 SWIG 的示例:

      调用C++函数“inflow”的Python代码:

       import inflow    # importing C++ inflow library
       nframes = 25
       print 'calling inflow function in loop ...'
       for i in xrange(0,1001):
            z = inflow.inflow(""" arguments""")
           """ code does something with z """
      

      C++ 函数将照常进行:

       #include <iostream>
       #include <vector>
        inflow(/* arguments from Python*/)
        {
         /* code does something */
      
        }
      

      现在要与 Python 交互,步骤如下:

      1) 重要 - 确保您在此步骤中尝试绑定的 C++ 代码的名称与之前的名称不同 命令中给出。否则它将被 swig 代码覆盖。

      假设 example_wrap.cpp 是您要与 Python 交互的文件,“example.i”是 SWIG 接口文件。 SWIG 将生成一个名为 example.cpp 的新文件。

      2) swig -c++ -python -o example_wrap.cpp example.i

      3) g++ -I /usr/include/python2.7 -fPIC -c example_wrap.cpp -o example_wrap.o

      4) g++ -shared -o _example.so example_wrap.o

      想法是编译后的模块名称应该以下划线开头,后跟名称。

      5) 在term中打开Python,然后说

      from example import *
      

      然后开始调用函数。

      6) 来源:http://www.iram.fr/~roche/code/python/SWIG.html#purpose

      示例的接口文件如下所示:

       %module example
       %{
         #include "example.h"
       %}
      
       %include "std_vector.i"
       // Instantiate templates used by example
       namespace std {
        %template(IntVector) vector<int>;
        %template(DoubleVector) vector<double>;
        }
      
        // Include the header file with above prototypes
        %include "example.h"
      

      【讨论】:

      • 您好 atmaere,我在第 4 步收到以下错误:“架构 x86_64 的未定义符号:'_PyArg_ParseTuple',引用自:teste.o 中的 _teste_swigregister”有什么想法吗?
      • 您的 C++ 代码中很可能存在语言错误。在连接之前,请确保您可以成功编译 C++ 代码(您将需要一个 main.cpp 文件)。 SWIG 调试消息不是很清楚。
      • 显然,当我在 Mac 上运行它时, -shared 选项不可用。相反,我应该使用 -dynamiclib 或 -bundle,根据 stackoverflow.com/questions/1494407/…
      • 如果您的问题已经被我满意地回答了,请不要忘记标记为答案:)。
      【解决方案4】:
      1. 我认为你应该看看boost python,它是一个了不起的库,也适用于 linux、windows 和 mac。使用 boost python,您可以导出您的类和函数,以便直接从 python 访问它们。例子很多,文档很好!!!

      2. 使用 boost python,您应该定义要公开的函数/类,它们会将您的源代码编译成一个库文件,该库文件将被导入到 python 中。

      【讨论】:

      • 感谢 Hugo,但我已经完成了工作,但将来会尝试您的解决方案
      【解决方案5】:

      简单、有效、快速的方法:

      无效方法

      test.cpp

      #include <iostream>
      extern "C" void Print()
      {
          std::cout << "This is data from inside a c++ file." << std::endl;
      }
      

      编译时命令

      g++ -c -fPIC test.cpp -o test.o // DO NOT FORGET '-fPIC'
      g++ -shared -o test.so test.o // FOR UNIX ONLY
      

      Main.py

      from ctypes import cdll
      
      test = cdll.LoadLibrary('./test.so')
      test.Print()
      

      传递和返回值

      在 test.cpp 中

      extern "C" int Multiply(int a, int b)
      {
          return a*b;
      }
      

      在 Main.py 中 从 ctypes 导入 cdll

      test = cdll.LoadLibrary('./test.so')
      value = test.Multiply(5,5)
      print(value)
      


      总结
      不需要额外的库。
      不需要构造函数。
      不需要 c++ 类。
      不需要公开声明。

      只需创建一个方法并将其标记为extern "C"
      然后在python中调用它。

      【讨论】:

        猜你喜欢
        • 2016-08-09
        • 1970-01-01
        • 2011-10-28
        • 1970-01-01
        • 1970-01-01
        • 2012-01-23
        • 2017-07-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多