簡體   English   中英

如何手動編譯使用C ++的Cython代碼?

[英]How can I manually compile Cython code that uses C++?

我已經完全復制了Cython文檔中給出的用於包裝C ++類的示例代碼。 我可以使用distutilscythonize()方法成功構建和導入rect.so擴展,即:

  1. 將以下指令放在rect.pyx的頂部:

     # distutils: language = c++ # distutils: sources = Rectangle.cpp 
  2. 編寫包含以下內容的setup.py文件:

     from distutils.core import setup from Cython.Build import cythonize setup( name = "rectangleapp", ext_modules = cythonize('*.pyx'), ) 
  3. 調用

     $ python setup.py build_ext --inplace 

但是,當我在Cython中包裝C代碼時,我經常發現從命令行手動編譯單個擴展更方便,即:

  1. 使用命令行Cython編譯器生成.c代碼

     $ cython foo.pyx 
  2. 使用gcc手動編譯它:

     $ gcc -shared -fPIC -O3 -I /usr/lib/python2.7 -L /usr/lib/python2.7 \\ foo.c -lpython2.7 -o foo.so 

我已經嘗試應用相同的過程來構建上面的rect.so示例:

$ cython --cplus rect.pyx
$ g++ -shared -fPIC -O3 -I /usr/lib/python2.7 -L /usr/lib/python2.7 \
      rect.cpp -lpython2.7 -o rect.so

Cython和g ++編譯步驟似乎都成功了 - 我沒有得到任何命令行輸出,最后我有一個rect.so構建。 但是,當我嘗試導入模塊時,我得到一個undefined symbol錯誤:

In [1]: import rect
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-1-ba16f97c2145> in <module>()
----> 1 import rect

ImportError: ./rect.so: undefined symbol: _ZN6shapes9Rectangle9getLengthEv

手動編譯包裝C ++類的Cython代碼的正確步驟是什么?

這里的問題是你說某個地方你將提供一個名為Rectangle的類的定義 - 示例代碼說明了這一點

cdef extern from "Rectangle.h" namespace "shapes":
    cdef cppclass Rectangle:
        ...

但是,當您編譯庫時,您沒有提供Rectangle的代碼或包含它的庫,因此rect.so不知道在哪里可以找到這個Rectangle類。

要運行代碼,必須首先創建Rectangle對象文件。

gcc -c Rectangle.cpp # creates a file called Rectangle.o

現在,您可以創建一個庫來動態鏈接,或者將目標文件靜態鏈接到rect.so 我將首先介紹靜態鏈接,因為它最簡單。

gcc -shared -fPIC -I /usr/include/python2.7 rect.cpp Rectangle.o -o rect.so

請注意,我沒有包含python庫。 這是因為您希望您的庫由python解釋器加載,因此加載庫時,進程已經加載了python庫。 除了提供rect.cpp作為源之外,我還提供了Rectangle.o 因此,讓我們嘗試使用您的模塊運行程序。

run.py

import rect
print(rect.PyRectangle(0, 0, 1, 2).getLength())

不幸的是,這會產生另一個錯

ImportError: /home/user/rectangle/rect.so undefined symbol: _ZTINSt8ios_base7failureE

這是因為cython需要c ++標准庫,但是python沒有加載它。 您可以通過將c ++標准庫添加到rect.so所需的庫來rect.so

gcc -shared -fPIC -I/usr/include/python2.7 rect.cpp Rectangle.o -lstdc++ \
     -o rect.so

再次運行run.py ,一切都應該有效。 但是, rect.so的代碼比它需要的大,特別是如果你生成多個依賴於相同代碼的庫。 您可以動態鏈接Rectangle代碼,也可以將其作為庫。

gcc -shared -fPIC Rectangle.o -o libRectangle.so
gcc -shared -fPIC -I/usr/include/python2.7 -L. rect.cpp -lRectangle -lstdc++ \
     -o rect.so

我們將Rectangle代碼編譯到當前目錄中的共享庫中並提供-L. 所以gcc知道在當前目錄和-lRectangle查找庫,所以gcc知道要查找Rectangle庫。 最后,為了能夠運行您的代碼,您必須告訴python Rectangle庫所在的位置。 在運行python之前輸入

export LD_LIBRARY_PATH="/home/user/rectangle" # where libRectangle.so lives

您可以使用shell腳本確保每次運行程序之前都執行此操作,但這會使事情變得更加混亂。 最好只是堅持靜態鏈接矩形。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM