Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointers and arrays in Python ctypes

I have a DLL containing a C function with a prototype like this:

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

I want to call it from Python using ctypes. The function expects a pointer to a chunk of memory, into which it will write the results. I don't know how to construct and pass such a chunk of memory. The ctypes documentation isn't much help.

Constructing an array and passing it "byref", like this:

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

Gives this error message:

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

I guess that is because the Python ulong array is nothing like a c uint32 array. Should I use create_char_string. If so, how do I persuade Python to "cast" that buffer to an LP_c_ulong?

like image 748
Andrew Bainbridge Avatar asked Sep 01 '09 15:09

Andrew Bainbridge


People also ask

What does ctypes do in Python?

ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python.

How do I use ctypes pointer?

Creating Pointers with ctypesPOINTER() takes as parameter the type of pointer you wish to create, an integer pointer for example. ctypes. pointer() takes as parameter an object, which it then returns a pointer to. The pointer() however, only accepts datatypes from the ctypes module.

Is ctypes a built in Python?

The built-in ctypes module is a powerful feature in Python, allowing you to use existing libraries in other languages by writting simple wrappers in Python itself. Unfortunately it can be a bit tricky to use. In this article we'll explore some of the basics of ctypes .


2 Answers

You can cast with the cast function :)

>>> 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> >>>  
like image 200
Mark Rushakoff Avatar answered Oct 02 '22 20:10

Mark Rushakoff


You can cast the result, but ctypes allows you to use an array in place of a pointer, directly. The issue is the byref in your code (which would be the equivalent of a pointer to a pointer):

So instead of:

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

try:

cresult = (c_ulong * num)() err = self.c_read_block(addr, cresult, num) 
like image 26
ephemer Avatar answered Oct 02 '22 21:10

ephemer