2013-04-22 70 views
2

我有一個古老而成熟的C++庫,它包含一個Matrix類和一大堆使用它的代碼。它基本上是如何使用SWIG爲Matrix類創建Numpy包裝?

class Matrix { 
    double* p;  // the actual data 
    int nd;   // number of dimensions 
    int d0, d1, d2; // the actual dimensionality 

    // ... (a whole lot of functions computing various things, like SVDs, dotproduct etc. 
} 

現在我們寫一個使用SWIG的python包裝器。我們想在Python一側使用NumPy數組來保持與世界其他地方的兼容。所以我們實際上不需要我們的C++ Matrix類的功能,但是我們想要使用我們庫的其他部分,它需要這個C++矩陣。因此,如果我們可以將NumPy數組的類型圖寫入Matrix類,並在每次調用時透明地轉換NumPy數組並保持內存同步,那麼完美的情況就是如此。比方說,我們有我們的圖書館,這是swigged一些功能:

int some_function(Matrix& in) { /* do some stuff */ } 

現在,這將是巨大的,如果在Python,我們可以這樣做:

a = numpy.array[1,2,3,4] 
b = some_function(a) 

我明白,有numpy.i ,但似乎更多的是關於函數映射和普通的舊C數組。我也明白一個類型映射應該實現我想要的,但我並不真正瞭解如何實際訪問numpy數據。有沒有(相對)簡單的方法來做到這一點?

我也很欣賞一些教程的指針。

回答

1

根據您提供的信息,typemaps可以工作。但我作爲間歇性SWIG用戶的經驗(通常是幾個星期,我使用它很多,然後中斷,直到下一個項目/階段),很少有人有時間去理解這個功能。

在你的情況,我相信痛飲typemaps更便利比的要求,所以我會用兩種方法之一:

  1. 創建一個Python函數,它從numpy.array到矩陣轉換(矩陣是通過SWIG選自C導出++到Python所述一個)
  2. 使用內建numpy.i類型映射調用一個C++函數,它接受在該類型映射爲C++類型,並且定義該函數調用int some_function(Matrix& in)

優點的選擇1,您可以通過重新綁定的Python功能自動化改造:

old_some_func = some_function 
def some_function(numpy_array): 
    tempMat = Matrix() 
    # convert numpy_array to SWIG'd Matrix class 
    old_some_func(tempMat) 

這樣做的性能影響可能是微不足道的,但你應該測試。如果沒有SWIG(即,如果您使用的是C API),該技術將具有不需要更改C++庫的額外優勢(請參閱SWIG的extend指令)。

選項2的優點是轉換是在C/C++級別,所以根據涉及的內容,您可能會獲得改進的性能。說一個numpy.i類型映射將numpy.array映射爲float [numValues]數組,並且您的C++矩陣保存單精度浮點值。在這種情況下,您可以在項目的.i文件中定義一個C++ some_function(float *,numValues),該函數調用some_function(Matrix)。檢查您的C++ Matrix類是否可以存儲指向數組數據的指針,這樣可以避免在一個甚至兩個層(Python - > SWIG some_function(array) - > some_function(Matrix))上覆制數據。

但請記住:您的C++ some_function中的計算可能會使這兩個選項之間的任何性能差異微不足道。你必須測試。然後去與最簡單和最可維護的(可能選項1)。