I wrote a C library to interface with a hardware device over USB, and have used the library successfully with other C code, so I know it works. I want to call this library from Python, and in order to do so I need to pass a struct by reference so that the library can modify it. The structure is defined:
typedef struct eventNode eventNode;
struct eventNode{
int channels;
int samples;
uint16_t** event;
eventNode* next;
eventNode* prev;
}
and in Python I have defined:
class eventNode(Structure):
pass
eventNode._fields_ = [("channels", c_int),
("samples", c_int),
("event",POINTER(POINTER(c_uint16))),
("prev",POINTER(eventNode)),
("next",POINTER(eventNode))]
which I believe is correct. Essentially I used this to implement a linked list, which my library can modify by calling a method with signature void getFromCAEN(int, char*, eventNode**, eventNode**). The last two arguments are pointers to pointers to the list head and tail, respectively. My python code creates these pointers by calling:
queueHead = POINTER(eventNode)()
queueTail = POINTER(eventNODE)()
which should initially be NULL (None in ctypes) so that the library knows the list is empty. When I call this function with the line
caenlib.getFromCAEN(handle,buff,byref(queueHead),byref(queueTail))
a linked list should be formed by the library, which I then attempt to index through with the following block:
cur = queueHead
while cur:
i+=1
print("event!",i)
print(addressof(cur))
print(cur.contents.channels,cur.contents.samples)
print(cur.contents.event)
print(cur.contents.next) #print next object in line
cur = cur.contents.next
print(cur) #this prints a different address for some reason
And the output of all those print statements is this:
event! 1
140486871191712
4 150
<__main__.LP_LP_c_ushort object at 0x7fc5a60d9200>
<__main__.LP_eventNode object at 0x7fc5a60d9170>
<__main__.LP_eventNode object at 0x7fc5a60d9290>
But the problem is, that even though I know there should be many events in the list, it only iterates once and then stops. The problem seems to be with those last few lines, that even though cur gets assigned to cur.contents.next, the address seems to change 0x...170 becomes 0x...290 after the assignment. Attempting to dereference cur after this point raises a NULL poitner exception. I think I'm missing something about pointers and assignment in Python, but I'm not sure what to do.
PS the access to cur.contents.channels and cur.contents.samples returns exactly what I expect it to for the one object that I am able to access, indicating that it is working at least partially.