SWIG 将 C++ 包装成 Python
SWIG Wrap C++ into Python
我编写了一个 C++ 模块来计算我的 SCARA 机器人手臂的正向和反向运动学,我想将这个模块包装到 Python 中,以便我可以在另一个应用程序中使用它。对于转换,我选择了SWIG,但是很难正确编写接口文件。
在我的 C++ 模块头文件中,我有
namespace ARM_KINEMATICS{
/*
Forward kinematics
[in] const double *q: joints' value
[out] double *T: placeholder to put homogeneous transformation matrix, with length 16
*/
void forward(const double *q, double *T);
/*
Inverse kinematics
[in] const double *T: target homogenous transformation matrix with length 16
[out] double q_sols: placeholder for solutions, with length 2*4
[out] int: number of solutions
*/
int inverse(const double *T, double *q_sols);
}
Python 中的预期行为类似于
> import arm_kinematics
> T = [0.0] * 16
> arm_kinematics.forward([0.0, 0.0, 0.0, 0.0], T)
> T
[1.0, 0.0, 0.0, 0.6, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.139, 0.0, 0.0, 0.0, 1.0]
> q_sols = [0.0] * 8
> num_sols = arm_kinematics.inverse(T, q_sols)
> q_sols[:num_sols*4]
[0.0, 0.0, 0.0, 0.0]
如何编写接口文件,以便它可以将 Python 列表转换为 C++ 数组,反之亦然?是否可以使 Python 通过引用传递 ?
我发现
typemap
可以处理已知数组大小的函数,例如int foo(int arr[4])
,但如果现在数组是通过指针传递的,而我们不知道它的大小,我应该如何修改接口文件?
提前致谢!
使用 SWIG 最简单的方法是使用 numpy.i
将您的 C++ 接口更改为此
namespace ARM_KINEMATICS{
/*
Forward kinematics
[in] const double *q: joints' value
[out] double *T: placeholder to put homogeneous transformation matrix, with length 16
*/
void forward(const double *q, const int nq, double **T, int* nT);
/*
Inverse kinematics
[in] const double *T: target homogenous transformation matrix with length 16
[out] double q_sols: placeholder for solutions, with length 2*4
[out] int: number of solutions
*/
int inverse(const double *T, const int nT, double **q_sols, int* nq_sols);
}
然后是 SWIG 的工作界面
%module robot
%{
#define SWIG_FILE_WITH_INIT
#include "robot.h"
%}
%include "numpy.i"
%init
%{
import_array();
%}
%apply (double* IN_ARRAY1, int DIM1) {(const double *q, const int nq)}
%apply (double* IN_ARRAY1, int DIM1) {(const double *T, const int nT)}
%apply (double** ARGOUTVIEWM_ARRAY1, int* DIM1) \
{(double** T, int* nT)}
%apply (double** ARGOUTVIEWM_ARRAY1, int* DIM1) \
{(double** q_sols, int* nq_sols)}
%include "robot.h"
如果你研究 numpy.i
,你会发现你也可以 input/output 矩阵。
类型映射在 numpy.i
中定义,它与 NumPy
一起提供
我编写了一个 C++ 模块来计算我的 SCARA 机器人手臂的正向和反向运动学,我想将这个模块包装到 Python 中,以便我可以在另一个应用程序中使用它。对于转换,我选择了SWIG,但是很难正确编写接口文件。
在我的 C++ 模块头文件中,我有
namespace ARM_KINEMATICS{
/*
Forward kinematics
[in] const double *q: joints' value
[out] double *T: placeholder to put homogeneous transformation matrix, with length 16
*/
void forward(const double *q, double *T);
/*
Inverse kinematics
[in] const double *T: target homogenous transformation matrix with length 16
[out] double q_sols: placeholder for solutions, with length 2*4
[out] int: number of solutions
*/
int inverse(const double *T, double *q_sols);
}
Python 中的预期行为类似于
> import arm_kinematics
> T = [0.0] * 16
> arm_kinematics.forward([0.0, 0.0, 0.0, 0.0], T)
> T
[1.0, 0.0, 0.0, 0.6, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.139, 0.0, 0.0, 0.0, 1.0]
> q_sols = [0.0] * 8
> num_sols = arm_kinematics.inverse(T, q_sols)
> q_sols[:num_sols*4]
[0.0, 0.0, 0.0, 0.0]
如何编写接口文件,以便它可以将 Python 列表转换为 C++ 数组,反之亦然?是否可以使 Python 通过引用传递 ? 我发现
typemap
可以处理已知数组大小的函数,例如int foo(int arr[4])
,但如果现在数组是通过指针传递的,而我们不知道它的大小,我应该如何修改接口文件?
提前致谢!
使用 SWIG 最简单的方法是使用 numpy.i
将您的 C++ 接口更改为此
namespace ARM_KINEMATICS{
/*
Forward kinematics
[in] const double *q: joints' value
[out] double *T: placeholder to put homogeneous transformation matrix, with length 16
*/
void forward(const double *q, const int nq, double **T, int* nT);
/*
Inverse kinematics
[in] const double *T: target homogenous transformation matrix with length 16
[out] double q_sols: placeholder for solutions, with length 2*4
[out] int: number of solutions
*/
int inverse(const double *T, const int nT, double **q_sols, int* nq_sols);
}
然后是 SWIG 的工作界面
%module robot
%{
#define SWIG_FILE_WITH_INIT
#include "robot.h"
%}
%include "numpy.i"
%init
%{
import_array();
%}
%apply (double* IN_ARRAY1, int DIM1) {(const double *q, const int nq)}
%apply (double* IN_ARRAY1, int DIM1) {(const double *T, const int nT)}
%apply (double** ARGOUTVIEWM_ARRAY1, int* DIM1) \
{(double** T, int* nT)}
%apply (double** ARGOUTVIEWM_ARRAY1, int* DIM1) \
{(double** q_sols, int* nq_sols)}
%include "robot.h"
如果你研究 numpy.i
,你会发现你也可以 input/output 矩阵。
类型映射在 numpy.i
中定义,它与 NumPy