python SWIG:重新定义类方法的签名以使用自定义类型Map

dgiusagp  于 2022-12-17  发布在  Python
关注(0)|答案(1)|浏览(142)

我有一个类的玩具模型,它的方法接受两个整数并将它们推到一个向量(通过引用传递)。我还有一些自定义类型Map,它们修改in/out参数,最重要的是将vector参数修改为Python的输出参数。到目前为止,当我将其声明为类外部的函数时,我可以在接口文件中重新定义它以使用类型Map,而无需重新声明,但我不能对类方法做同样的事情。
我的玩具模型看起来像这样:

/* example.hpp */
#include <vector>
#include <iostream>

void some_func(int x, int y, std::vector<int>* res);

class SampleClass
{
public:
  ...
    void two_args(int x, int y, std::vector<int>* vec);
  ...

};
/* example.cpp */

void some_func(int x, int y, std::vector<int>* res){
    res->push_back(x);
    res->push_back(y);
}
void SampleClass::two_args(int x, int y, std::vector<int>* vec){
     vec->push_back(x);
     vec->push_back(y);
}
/* interface.i */
%module example

%{
    #include "example.hpp"
%}

%include "typemaps.i"
%include "std_vector.i"

%template(doublevector) std::vector<double>;
%template(intvector) std::vector<int>;

/* NOTE: This mostly works but not for constructor */
%apply std::vector<double> *INPUT {std::vector<double>* };

/* Ignore vec as input argument and set it to a temp val */
%typemap(in, numinputs=0) std::vector<int>* VecOutInt (std::vector<int> tmp){
    $1 = &tmp;
}

/* Return a list to python */
%typemap(argout) std::vector<int>* VecOutInt {
    size_t size = (*$1).size();
    $result = PyList_New(size);
    Py_ssize_t idx = 0;
    for (idx = 0; idx < size; ++idx){
        PyObject *o = PyLong_FromLong($1->at(idx));
        PyList_SetItem($result, idx, o);
}
}
void some_func(int x, int y, std::vector<int> * VecOutInt); // Redifinition works fine here.
void SampleClass::two_args(int x, int y, std::vector<int>* VecOutInt); // But not here. (I guess?)
%include "example.hpp"

/* python */
>>> a = ex.some_func(1, 2)
>>> a
[1, 2]
>>> ex_cls = ex.SampleClass().two_args(1, 2)
default constructor!
Traceback (most recent call last):                                                                                                                                                                                     File "<stdin>", line 1, in <module>                                                                                                                                                                                TypeError: two_args() missing 1 required positional argument: 'vec'

本质上,我试图将这个类型Map应用到这个特定的方法,或者至少是它的特定签名(但更关注方法部分)。我从邮件列表中找到了这个线程here,这几乎是我遇到的问题,但没有实际的/确定的答案。有没有办法在接口文件中重新定义类方法?更改C++代码不是一个选项。谢谢!

am46iovg

am46iovg1#

下面是一个工作示例,在这种情况下,您所需要的只是应用一个OUTPUT类型Map:

示例.hpp

#include <vector>

void some_func(int x, int y, std::vector<int>* res);

class SampleClass
{
public:
    void two_args(int x, int y, std::vector<int>* vec);
};

示例.cpp

#include "example.hpp"

void some_func(int x, int y, std::vector<int>* res) {
    res->push_back(x);
    res->push_back(y);
}

void SampleClass::two_args(int x, int y, std::vector<int>* vec) {
     vec->push_back(x);
     vec->push_back(y);
}

示例.i

%module example

%{
#include "example.hpp"
%}

%include "std_vector.i"
%template(intvector) std::vector<int>;

%apply std::vector<int>* OUTPUT {std::vector<int>*};
%include "example.hpp"

输出:

>>> import example as e
>>> e.some_func(1, 2)
(1, 2)
>>> s = e.SampleClass()
>>> s.two_args(3, 4)
(3, 4)

注意,如果您有一些向量作为输入,一些向量作为输出,那么您可以通过命名参数来显式地%applyOUTPUT类型Map,例如:

%apply std::vector<int>* OUTPUT {std::vector<int>* vec};
%apply std::vector<int>* OUTPUT {std::vector<int>* res};

即使两个函数中的参数名称相同,但一个用作输入,一个用作输出,如果它们相差const,您仍然可以分别应用它们:

%apply std::vector<int>* INPUT {const std::vector<int>* vec};
%apply std::vector<int>* OUTPUT {std::vector<int>* vec};

相关问题