2016-10-17 11 views
0

現在、ctypesライブラリを使用してc関数を呼び出すpythonコールバック関数があります。 c関数は、たとえばanimal_info_sのような構造体へのポインタを必要とします。私は構造体をインスタンス化し、それをc関数へのポインタとして渡します。私が抱えている問題は、コールバックを呼び出す複数のスレッドがある場合です。返される情報がスレッド間で混在していることがわかります。Python Ctypes関数のメモリ割り当て

class animal_info_s(ctypes.Structure): 
    _fields_ = [('dog_type',   ctypes.c_uint16), 
       ('cat_type',   ctypes.c_uint16), 
       ('bird_type',   ctypes.c_uint16), 
       ('epoch_time',  ctypes.c_uint16), 
       ('more_information', ctypes.c_uint16)] 


_mod = ctypes.cdll.LoadLibrary('bbuintflib.dll') 
animal_info_s = animal_info_s() 
get_animal_data = _mod.get_animal_data 
get_animal_data.argtypes = [ctypes.POINTER(animal_info_s)] 
get_animal_data.restype = ctypes.c_int 

# Python Callback 
def GetAnimalData(): 
    animal_info_p = animal_info_s 
    res = get_animal_data(animal_info_p) 
    if (res != 0): 
     print("Failed to get animal info") 
     return 

    print ("Receive Time - %d\nDog: %d\nCat: %d\nBird:%d" %(animal_info_p.epoch_time, 
                  animal_info_p.dog_type, 
                  animal_info_p.cat_type, 
                  animal_info_p.bird_type)) 

私は構造体をインスタンス化するときに、毎回同じメモリ位置を使用していると思います。コールバックを呼び出すスレッドごとに新しいメモリ位置を作成するにはどうすればよいですか?

+1

私はctypesのエキスパートではありませんが、スレッドごとに 'GetAnimalData'で' animal_info_p = animal_info_s'を使用していますか?それはどこでも同じ構造体インスタンスを使用しています(そして、奇妙な動作を説明します)。代わりに 'animal_info_p = animal_info_s()'をしたくないですか? – rkersh

答えて

2

次の行は削除する必要があります。 animal_info_sという名前をclass animal_info_sインスタンスとして再定義し、クラスを非表示にします。

animal_info_p = animal_info_s 

animal_info_s = animal_info_s() 

次の行から変更する必要があり

animal_info_p = animal_info_s() 

元の行は、一つであった、最初のエラーからanimal_info_s名の別の名前を作っスレッド内で使用される - と - のみのインスタンス。推奨される行は、コールバックが呼び出されるたびにanimal_info_sクラスの新しいインスタンスを作成します。

+0

animal_info_sの新しいインスタンスを作成するときに、使用するメモリを解放する必要がありますか、それともPythonが処理するのですか? Pythonは通常それを処理しますが、これは特別なケースです(このオブジェクトはC言語用です)、どこかでメモリリークが発生する可能性があります。 – Sam

+0

インスタンスが関数の終わりにスコープから外れると、Pythonによって解放されます。 C関数がメモリへの参照を保持していた場合、C関数がそれを必要とする限り、Pythonでオブジェクトへの参照を保持する必要があります。 –