ctypesを介してCライブラリにアクセスしていますが、次の問題が発生します。
ctypeslibを使用して「ラッパー」(ctypesでライブラリにアクセスするためのctypesコマンド)を生成しています。Cライブラリには、このステップでPython関数に変換されるマクロが含まれています。(ライブラリの内部から可能な限り独立させるために、Pythonでこれらのマクロのいくつかを使用したいと思います。)
これらのマクロの1つは次のようになります。
# using the ctypes types
myuint16_t = c_ushort
myuint32_t = c_ulong
def mymacro(x): return (myuint16_t)((myuint32_t)(x) >> 16) # macro
生成された関数を別のモジュールで次のように使用したい(関数内):
return wrapper.mymacro(valueToBeConverted) # valueToBeConverted is an int
しかし、この行を使用すると、次のエラーが発生しました。
....
def mymacro(x): return (myuint16_t)((myuint32_t)(x) >> 16) # macro
TypeError: unsupported operand type(s) for >>: 'c_ulong' and 'int'
(c_ulongをシフトする一般的な方法は知っていc_ulongvar.value >> x
ますが、Cライブラリで何かが変更されるたびに、生成されたラッパーにパッチを適用する必要があります。したがって、これは避けようとします)。
ここではc_ulongの__rshift__
実装は使用できないようです。
print c_ulong.__rshift__
# throws AttributeError: type object 'c_ulong' has no attribute '__rshift__'
うーん、奇妙に思えます...そこで__rshift__
、c_ulongのメソッドを再実装して機能させることにしました。
from ctypes import *
from types import MethodType
def rshift(self, val):
print self.value >> val
# create an unbound method which applies to all (even existing) instances
c_ulong.__rshift__ = MethodType(rshift, None, c_ulong)
a = c_ulong(1)
a >> 16
しかし、それは問題を解決しません。まだエラーが発生しています:
a >> 16
TypeError: unsupported operand type(s) for >>: 'c_ulong' and 'int'
__rshift__
メソッドが同じクラスの2つのインスタンスにのみ使用できる可能性はありますか?私は次のことを試しました:
def rshift(self, val):
print self.value >> int(val.value)
a = c_ulong(1)
a >> c_ulong(16)
そしてそれは動作します。ただし、生成されたラッパーにパッチを適用する必要があることも意味します。
だから:誰かがここでのトリックを知っていますか?
更新:
@eryksunのソリューションは機能しました。使ってます:
from ctypes import *
# from types import MethodType
def _rshift(self, other):
if hasattr(other, 'value'):
other = other.value
return c_ulong(self.value >> other)
def _lshift(self, other):
if hasattr(other, 'value'):
other = other.value
return c_ulong(self.value << other)
def _coerce(self, other):
try:
return self, self.__class__(other)
except TypeError:
return NotImplemented
# Add the functions to the type. A method is created when
# accessed as an attribute of an instance.
c_ulong.__lshift__ = _lshift
c_ulong.__rshift__ = _rshift
c_ulong.__coerce__ = _coerce