I'm sorry, but I generally have a hard time reading the current ctypes docs...
If I have a C function that takes a const char *
pointer, and I know it will neither modify the passed in string, nor keep a reference to it beyond the function call, it really makes sense to pass in a pointer directly to the bytes of a python string.
Can ctypes can do this or is it just plain unsupported? Do I really have to create_string_buffer
and copy my string into it?
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.
Python utilizes a system, which is known as “Call by Object Reference” or “Call by assignment”. In the event that you pass arguments like whole numbers, strings or tuples to a function, the passing is like call-by-value because you can not change the value of the immutable objects being passed to the function.
The pythonic way of dealing with this is to hold strings in an list and join them together once you have all the pieces. Python never passes by reference. It passes references, but "pass by reference" is already taken for another argument passing style (one which permits, for example, the function swap(a, b) ).
ctypes is the de facto standard library for interfacing with C/C++ from CPython, and it provides not only full access to the native C interface of most major operating systems (e.g., kernel32 on Windows, or libc on *nix), but also provides support for loading and interfacing with dynamic libraries, such as DLLs or ...
Assigning a new value to instances of the pointer types c_char_p, c_wchar_p, and c_void_p changes the memory location they point to, not the contents of the memory block (of course not, because Python strings are immutable):
>>> s = "Hello, World" >>> c_s = c_char_p(s) >>> print c_s c_char_p('Hello, World') >>> c_s.value = "Hi, there" >>> print c_s c_char_p('Hi, there') >>> print s # first string is unchanged Hello, World >>>
You should be careful, however, not to pass them to functions expecting pointers to mutable memory. If you need mutable memory blocks, ctypes has a create_string_buffer function which creates these in various ways. The current memory block contents can be accessed (or changed) with the raw property, if you want to access it as NUL terminated string, use the string property:
Says the ctypes tutorial. What I gather from this is that only if the function would work with a const char*
, would passing in the python string be valid. Keep in mind, it won't have a null termination.
I'd suggest using create_string_buffer
anyhow.
The type ctypes.c_char_p represents a nul-terminated string. If a function takes a const char* you can pass a Python string to it and it will receive a nul-terminated version.
A Windows example DLL:
#include <string.h>
__declspec(dllexport) char* func(char* a,size_t len,const char* b)
{
if(strlen(b) * 2 >= len)
return NULL;
strcpy_s(a,len,b);
strcat_s(a,len,b);
return a;
}
Python:
Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import *
>>> x=CDLL('x')
>>> x.func.restype=c_char_p
>>> x.func.argtypes=[c_char_p,c_int,c_char_p]
>>> s=create_string_buffer(10)
>>> x.func(s,len(s),'abcd')
'abcdabcd'
>>>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With