7

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?

2 Answers 2

18

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.

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

6 Comments

Thanks, you are entirely correct. I even vaguely remember reading this before. I despise the ctypes docs for putting key information in the tutorials.
I hear you on that. Python documents are great, except when you need to look something up. Then you'll need to read everything related to what you want to do. I can't stress enough though, the string you pas in will not be null terminated. So do not use any std::string or string.h functions on them. )
a Python string passed to ctypes will be nul-terminated. It is valid to pass a Python string to a function that takes the c_char_p type.
it'll only be null terminated is you pass it through create_string_buffer. python strings have no null terminator.
Look closely at all the examples in the ctypes tutorial. The examples call printf, strchr, etc. with Python strings and they will be nul-terminated. create_string_buffer is only needed for mutable strings.
|
6

The type ctypes.c_char_p represents a nul-terminated string. If a C 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:

// test.c - cl /LD test.c
#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('test')
>>> 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'

2 Comments

Python docs say ... "None, integers, longs, byte strings and unicode strings are the only native Python objects that can directly be used as parameters in these function calls. ... byte strings and unicode strings are passed as pointer to the memory block that contains their data (char * or wchar_t *)." ... in the section on Calling Functions, right before Fundamental Data Types
Python documentation for the Python C API function PyString_AsString: Return a NUL-terminated representation of the contents of string. The pointer refers to the internal buffer of string, not a copy. The internal string buffers are nul-terminated.

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.