簡體   English   中英

使用 SWIG 在 Python 中包裝 C++ 類

[英]Wrapping C++ class in Python with SWIG

我有以下 C++ 類,我希望使用 SWIG 將其包裝在 Python 中。

typedef std::map<std::string, double> ParamaterSet;

class GPRegressor{
public:
    double runRegression(const double *trainData, const double *trainTruth, int trainRows, int trainCols,
                             const double *testData, const double *testTruth, int testRows, int testCols,
                             const ParamaterSet &params);

    GPRegressor(KernelType kernType = SQUARED_EXPONENTIAL);
    ~GPRegressor();
    };

我編寫了以下 SWIG 接口文件,以允許我將 numpy 數組傳遞給runRegression成員函數。

%module pyGP
%{
#define SWIG_FILE_WITH_INIT
#include "lib/typedefs.h"
#include "lib/Kernels.h"
#include "lib/GPRegressor.h"
%}

%include "numpy.i"
%include "std_string.i"
%include "std_map.i"
%template(map_string_double) std::map<std::string, double>;

%init %{
  import_array();
%}

%apply (const double *arr, int dim1, int dim2) {(const double *data, int dimx, int dimy)}
%apply (double *arr, int dim1, int dim2) {(double *data, int dimx, int dimy)}

%include "lib/typedefs.h"
%include "lib/Kernels.h"
%include "lib/GPRegressor.h"

我相信我已經正確地編寫了 SWIG 類型映射以允許我這樣做。 我編寫了以下 Python 測試代碼。

#!/usr/bin/python3
import sys, os
sys.path.append(os.path.realpath('../build'))
import numpy as np

from pyGP import *

def runRegression():
    X = np.random.rand(30, 2)
    Y = np.random.rand(30, 1)
    X_s = np.random.rand(30, 2)
    Y_s = np.random.rand(30, 1)

    regressor = GPRegressor()
    regressor.runRegression(X, Y, 30, 2, X_s, Y_s, 30, 1, {'a' : 0.0, 'b' : 0.0})

if __name__ == "__main__":
    runRegression()

但是,我收到以下錯誤,這意味着我實際上在使用 numpy 數組的類型映射時犯了一個錯誤。

Traceback (most recent call last):
  File "./demo.py", line 22, in <module>
    runRegression()
  File "./demo.py", line 18, in runRegression
    regressor.runRegression(X, Y, 30, 2, X_s, Y_s, 30, 1, {'a' : 0.0, 'b' : 0.0})
  File "/home/jack/GitRepos/GaussianProcess/build/pyGP.py", line 337, in runRegression
    return _pyGP.GPRegressor_runRegression(self, trainData, trainTruth, trainRows, trainCols, testData, testTruth, testRows, testCols, params)
TypeError: in method 'GPRegressor_runRegression', argument 2 of type 'double const *'

總而言之,我想知道我嘗試包裝類的方式及其成員函數以便我可以將 numpy 數組傳遞給const double*方式實際上是否正確。 如果不是,那么約定是什么?

編輯:-我已更新 SWIG 文件以包含以下內容:

%apply (double *IN_ARRAY2, int DIM1, int DIM2) {(const double *trainData, int trainCols, int trainRows)};
%apply (double *IN_ARRAY1, int DIM1) {(const double *trainTruth, int trainRows)};
%apply (double *IN_ARRAY2, int DIM1, int DIM2) {(const double *testData, int testCols, int testRows)};
%apply (double *IN_ARRAY1, int DIM1) {(const double *testTruth, int testRows)};

並將要包裝的函數的簽名更改為以下內容:

double runRegression(const double *trainData, int trainCols, int trainRows, const double *trainTruth,
                     int trainTruthRows, const double *testData, int testCols, int testRows,
                     const double *testTruth, int testTruthRows, const ParamaterSet &params);

以便參數的順序與類型映射的順序相匹配。 但是,我仍然收到以下錯誤:

Traceback (most recent call last):
  File "./demo.py", line 23, in <module>
    runRegression()
  File "./demo.py", line 19, in runRegression
    regressor.runRegression(X, 2, 30, Y, 30, X_s, 2, 30, Y_s, 30, {'a' : 0.0, 'b' : 0.0})
TypeError: runRegression() takes 6 positional arguments but 12 were given

如果查看numpy.i標頭中的示例,您將看到如何應用NumPy映射的示例。

在你的情況下,你應該改變

%apply (double *arr, int dim1, int dim2) {(double *data, int dimx, int dimy)}

進入

%apply (double* IN_ARRAY2, int DIM1, int DIM2) {(const double *testTruth, int testRows, int testColsdouble)};

%apply (double* IN_ARRAY2, int DIM1, int DIM2) {(const double *trainTruth, int trainRows, int trainCols)};

注意如何使用IN_ARRAY2

我認為當你將你的 numpy ndarray 提供給你的 C++ 函數時,你不應該添加你的 ndarray 維度信息,在你的情況下是: 2, 30, 30...

相反,只需提供如下參數: regressor.runRegression(X, Y, X_s, Y_s, {'a' : 0.0, 'b' : 0.0})

暫無
暫無

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

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