Wskaźniki i tablice w Pythonie ctypes

Mam DLL zawierający funkcję C z prototypem takim jak:

int c_read_block(uint32 addr, uint32 *buf, uint32 num);

Chcę wywołać go z Pythona używając ctypes. Funkcja oczekuje wskaźnika do kawałka pamięci, do którego będzie zapisywać wyniki. Nie wiem jak skonstruować i przekazać taki kawałek pamięci. Dokumentacja ctypes nie jest zbyt pomocna.

Konstruowanie tablicy i przekazywanie jej "byref", Tak:

    cresult = (c_ulong * num)()
    err = self.c_read_block(addr, byref(cresult), num)

Wyświetla komunikat o błędzie:

ArgumentError: argument 3: <type 'exceptions.TypeError'>: expected LP_c_ulong instance instead of pointer to c_ulong_Array_2

Myślę, że to ponieważ tablica ULong Pythona w niczym nie przypomina tablicy c uint32. Czy powinienem używać create_char_string. Jeśli tak, to jak przekonać Pythona do "oddania" tego bufora do lp_c_ulong?

Author: Andrew Bainbridge, 2009-09-01

3 answers

Możesz obsadzić z cast Funkcja:)

>>> import ctypes
>>> x = (ctypes.c_ulong*5)()
>>> x
<__main__.c_ulong_Array_5 object at 0x00C2DB20>
>>> ctypes.cast(x, ctypes.POINTER(ctypes.c_ulong))
<__main__.LP_c_ulong object at 0x0119FD00>
>>> 
 49
Author: Mark Rushakoff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-01 16:10:10

Możesz rzucić wynik, ale ctypes pozwala użyć tablicy zamiast wskaźnika bezpośrednio. Problemem jest byref w Twoim kodzie (który byłby odpowiednikiem wskaźnika do wskaźnika):

Więc zamiast:

cresult = (c_ulong * num)()
err = self.c_read_block(addr, byref(cresult), num)

Spróbuj:

cresult = (c_ulong * num)()
err = self.c_read_block(addr, cresult, num)
 0
Author: ephemer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-24 12:31:00

W rozwiązaniu jest literówka. Aby uzyskać wskaźnik do tablicy ulongs musisz rzucić do POINTER(list of ulong)

In [33]: ptr = ctypes.cast(x, ctypes.POINTER(ctypes.c_ulong*5))
In [34]: ptr
Out[34]: <__main__.LP_c_ulong_Array_5 at 0x23e2560>
 -1
Author: bemehow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-25 17:41:09