2012-02-19 4 views
2

私はPyLongにC++構造体から型マップを作成しようとしています。swig typemapをC++構造体からPyLongに

たとえば、私は128ビットの数値を表す次の構造体を持っています。単純なPythonのunsigned longとしてPythonインターフェイスにアクセスしたいと思います。

struct my_128 { 
    u_int64_t raw[2]; 
}; 

どうすればこのようなタイプマップを作成できますか?

答えて

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); 
} 
+0

+1、それは私のソリューションよりもはるかに立派だ - 私は 'PyNumber'機能がありませんでした – Flexo

0

私は動作するものがありますが、それほど美しいものではありません。問題は、CからPyLongを作成する唯一の方法で、long longis 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()通話の「短い」整数を処理しませんが。

関連する問題