私はPyLongにC++構造体から型マップを作成しようとしています。swig typemapをC++構造体からPyLongに
たとえば、私は128ビットの数値を表す次の構造体を持っています。単純なPythonのunsigned longとしてPythonインターフェイスにアクセスしたいと思います。
struct my_128 {
u_int64_t raw[2];
};
どうすればこのようなタイプマップを作成できますか?
私はPyLongにC++構造体から型マップを作成しようとしています。swig typemapをC++構造体からPyLongに
たとえば、私は128ビットの数値を表す次の構造体を持っています。単純なPythonのunsigned longとしてPythonインターフェイスにアクセスしたいと思います。
struct my_128 {
u_int64_t raw[2];
};
どうすればこのようなタイプマップを作成できますか?
不在フルエラーチェック、これらのタイプマップは動作:
%typemap(in) struct my_128 {
PyObject* temp;
PyObject* shift;
if(!PyLong_Check($input) && !PyInt_Check($input))
{
PyErr_SetString(PyExc_TypeError,"Must be int or long type");
return NULL;
}
$1.raw[0] = PyInt_AsUnsignedLongLongMask($input); // low 64-bits
shift = PyInt_FromLong(64);
temp = PyNumber_Rshift($input,shift);
$1.raw[1] = PyInt_AsUnsignedLongLongMask(temp); // high 64-bits
Py_DECREF(temp);
Py_DECREF(shift);
}
%typemap(out) struct my_128 {
PyObject* low;
PyObject* high;
PyObject* shift;
PyObject* intermediate;
low = PyLong_FromUnsignedLongLong($1.raw[0]);
high = PyLong_FromUnsignedLongLong($1.raw[1]);
shift = PyInt_FromLong(64);
intermediate = PyNumber_Lshift(high,shift);
$result = PyNumber_Add(low,intermediate);
Py_DECREF(low);
Py_DECREF(high);
Py_DECREF(intermediate);
Py_DECREF(shift);
}
私は動作するものがありますが、それほど美しいものではありません。問題は、CからPyLongを作成する唯一の方法で、long long
is with a stringより長いことです。 stringstream
に進でそれを印刷した後、そこからPyLongを構築
%typemap(out) my_128 {
std::ostringstream s;
s << "0x"
<< std::setfill('0') << std::setw(8) << std::hex << $1.raw[0]
<< std::setfill('0') << std::setw(8) << std::hex << $1.raw[1];
char *c = strdupa(s.str().c_str()); // Avoids a const cast without leaking ever
$result = PyLong_FromString(c,0,0);
}
:あなたのmy_128
を受け取り、それはあなたが行うことができます関数から返されたときPyLongとしてそれを公開するタイプマップについては、これ
。
対応するtypemapは逆になります。私たちはPyLongをとり、組み込み関数hex()
を呼び出すことによってPythonを適切な文字列に変換するようにPythonを説得する必要があります。
次に、私たちが読むことができるもの(2つ)stringstreams
にマッサージする必要があります(そうしないと、すべての入力を盗みます)。これは、次のようになります。
これは、さらに多くのエラー処理を使用することができます。
私はこれらをテスト:
迅速な初期の試験から得られ%module test
%{
#include <sstream>
#include <iomanip>
#include <string.h>
#include <iostream> //for testing
%}
// Typemaps go here
%inline {
struct my_128 {
u_int64_t raw[2];
};
my_128 create() {
const my_128 r = {0xdeadbeef, 0xdeadbeef};
return r;
}
void display (my_128 in) {
std::cout << std::setfill('0') << std::setw(8) << std::hex << in.raw[0]
<< std::setfill('0') << std::setw(8) << std::hex << in.raw[1] << std::endl;
}
}
:
Python 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import test >>> test.create() 16045690984833335023L >>> test.display(16045690984833335023L) deadbeefdeadbeef >>> test.display(test.create()) deadbeefdeadbeef >>> test.display(test.create()+1) deadbeefdeadbef0 >>> test.display(test.create()+100) deadbeefdeadbf53 >>> test.display(test.create()+10000000) deadbeefdf46556f >>> test.display(test.create()+100000000000000000000) Traceback (most recent call last): File "", line 1, in ValueError: Expected at most a 128-bit int >>> test.display(test.create()+100000000000000000) e01104683c37beef >>> test.display(test.create()+10000000000000) deadc8082d205eef >>>
それはまだ正しくためsubstr()
通話の「短い」整数を処理しませんが。
+1、それは私のソリューションよりもはるかに立派だ - 私は 'PyNumber'機能がありませんでした – Flexo