python - How can I write a function to accept a Fraction object in SWIG?
问题描述
I'm writing an interface between Python and a our C++ video-processing library using SWIG. In python, I use the Fraction
class to represent frame rate (e.g. NTFS24 = 24000/1001 FPS). The functionality in question is video transcoding, i.e. taking a video (or a stream of frames) input and producing a similar output. For that we need to specify the output (and sometimes input) frame rate.
Is there any way I can interface the Fraction class on the C++ (SWIG) side? From what I found around the Internet I should be able to pass a tuple
to a std::pair<int,int>
parameter, so that's my fallback plan, but is there a better way? Thanks!
解决方案
我将以下接口文件放在一起来说明包装 Fraction 的工作原理。最后我决定创建自己的分数结构来保存 C++ 端的分数,主要是因为它比使用std::pair<int, int>
. (我认为一对整数也可以是 2D 坐标,或屏幕分辨率或许多其他类型,更强的类型对于重载分辨率等来说是更好的选择。)
%module test
%{
#include <iostream> // Just for testing....
static PyObject *fractions_module = NULL;
%}
%init %{
// Import the module we want
fractions_module = PyImport_ImportModule("fractions");
assert(fractions_module);
// TODO: we should call Py_DECREF(fractions_module) when our module gets unloaded
%}
%typemap(in) const Fraction& (Fraction tmp) {
// Input typemap for fraction: duck-type on attrs numerator, denominator
PyObject *numerator = PyObject_GetAttrString($input, "numerator");
PyObject *denominator = PyObject_GetAttrString($input, "denominator");
int err = SWIG_AsVal_int(numerator, &tmp.numerator);
assert(SWIG_IsOK(err)); // TODO: proper error handling
err = SWIG_AsVal_int(denominator, &tmp.denominator);
assert(SWIG_IsOK(err)); // TODO: errors...
Py_DECREF(numerator);
Py_DECREF(denominator);
$1 = &tmp;
}
%typemap(out) Fraction {
// Output typemap: pass two ints into fractions.Fraction() ctor
$result = PyObject_CallMethod(fractions_module, "Fraction", "ii", $1.numerator, $1.denominator);
}
%inline %{
struct Fraction {
int numerator, denominator;
};
void fraction_in(const Fraction& fraction) {
std::cout << fraction.numerator << "/" << fraction.denominator << "\n";
}
Fraction fraction_out() {
Fraction f = {100, 1};
return f;
}
%}
大多数情况下,这只是两个类型映射 - 一个用于 C++ 函数的输入,一个用于输出。他们从输入对象的分子和分母属性构造一个临时的 C++ 分数,并fractions.Fraction
分别从我们的 C++ 构造一个 Python 对象。将它们调整为其他类似的小数类型应该相当简单。
推荐阅读
- c++ - 通过socket c++发送长度和数据
- r - 在 case_when() 中抛出错误
- java - 编写一个程序,打印一行中两个选定数字的乘积
- c - 在 Fortran 中使用 FFTW 的 r2r 类型的 3-D 正弦变换中的泊松方程求解器
- .net - What's the difference between 'dotnet-sdk-2.1.401-osx-x64.pkg' and 'dotnet-sdk-2.1.401-osx-gs-x64.pkg'?
- python - Pandas isna() 和 isnull(),有什么区别?
- amazon-web-services - AWS 云形成;将模板分解为多个文件并使用 cfn-include 传入变量
- algorithm - 确定乘积和多项式中最佳权重的快速算法?
- scala - Scala Hello World:NoSuchMethodError:java.nio.ByteBuffer.clear
- javascript - 滚动后触发JQuery动画scrollTop