1

I currently have a python callback function that calls a c function using ctypes library. The c function requires a pointer to a structure for example animal_info_s. I instantiate the structure and pass it as a pointer to the c function and it works. The issue I'm having is when I have multiple threads calling the callback, I'm finding the information being passed back is mixed up between the threads.

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))

I think what is happening is when I instantiate the structure, it is using the same memory location every time. How do I create a new memory location for each thread calling the callback?

1
  • 1
    I'm not a ctypes expert, but are you using animal_info_p = animal_info_s in GetAnimalData for each thread? That would be using the same struct instance everywhere (and would explain the strange behavior). Don't you want animal_info_p = animal_info_s() instead? Commented Oct 17, 2016 at 20:11

1 Answer 1

2

The following line should be removed. It redefines the name animal_info_s as a class animal_info_s instance, which then hides the class.

animal_info_s = animal_info_s()

The following line should be changed from:

animal_info_p = animal_info_s

to:

animal_info_p = animal_info_s()

The original line made another name for the animal_info_s name from the first error, which was the one-and-only instance used in the threads. the recommended line creates a new instance of the animal_info_s class each time the callback is called.

Sign up to request clarification or add additional context in comments.

2 Comments

When creating an new instance of animal_info_s, do I have to free any memory used or does it get handled by Python? Python normally handles it but I'm worried this is a special case (This object is for C) and it might create a memory leak somewhere.
It is freed by Python when the instance goes out of scope at the end of the function. If a C function kept a reference to the memory, you would have to keep a reference to the object in Python as long as the C function needs it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.