ctypes.cast() is used to convert one ctype instance to another ctype datatype. You don't need it To convert it to python string. Just use ".value" to get it in python string.

>>> s = "Hello, World"
>>> c_s = c_char_p(s)
>>> print c_s
c_char_p('Hello, World')
>>> print c_s.value
Hello, World

More info here

Answer from Rajendran T on Stack Overflow
🌐
Python
python-list.python.narkive.com › pJK2bMLY › ctypes-delay-conversion-from-c-char-p-to-string
ctypes: delay conversion from c_char_p to string
Is there some way to tell ctypes to return an actual c_char_p, or is my best bet to return a c_void_p and cast to c_char_p when I'm reading to convert to a string? Yes, there is. When you create a subclass of c_char_p (or any other 'simple' ctypes type like c_wchar_p or even c_int and alike) then the automatic conversion to native Python types like string, unicode, integer is not done.
🌐
BestDivision
bestdivision.com › spread your knowledge - bestdivision › questions - bestdivision › python questions - categories - bestdivision › how to convert a c_char_p to a python string in ctypes? - bestdivision
How to convert a c_char_p to a Python string in ctypes? | BestDivision
July 15, 2023 - Before you begin, make sure to import the ctypes module to access the c_char_p type. You can create a c_char_p variable, which can hold a C-style string. Here’s an example: To convert the c_char_p variable to a Python string, you can use the .value attribute of the c_char_p variable and then ...
🌐
CodersLegacy
coderslegacy.com › home › python › python ctypes tutorial
Python ctypes Tutorial - CodersLegacy
October 27, 2022 - When using character pointers, we aren’t exactly dealing with mutable memory. The memory in question was still immutable. If we try assigning a new value to it, a new memory location will be assigned to the string with that value. Instead of the old memory location being assigned a new value. This can cause problems with functions which expect to receive mutable memory. The below example illustrates this issue. import ctypes clibrary = ctypes.CDLL('clibrary.so') cstring = ctypes.c_char_p(b"Hello") print("Before:" , cstring, cstring.value) cstring.value = b"World" print("After: ", cstring, cstring.value)
🌐
ProgramCreek
programcreek.com › python › example › 1243 › ctypes.c_char_p
Python Examples of ctypes.c_char_p
Parameters ---------- string : string type Python string. Returns ------- str : c_char_p A char pointer that can be passed to C API. Examples -------- >>> x = mx.base.c_str("Hello, World") >>> print x.value Hello, World """ return ctypes.c_char_p(string)
Top answer
1 of 2
17
from ctypes import *

charptr = POINTER(c_char)

test = CDLL('test.so')
test.initializetest.argtypes = []
test.initializetest.restype = charptr
test.searchtest.argtypes = [charptr]
test.searchtest.restype = c_int

buf = test.initializetest()
test.searchtest(buf)
print cast(buf, c_char_p).value
# TODO Release the "buf" memory or it will leak.

EDIT

Initially I used c_char_p to pass the buffer between the functions but c_char_p is like a const pointer. If used as a restype, you will actually get a Python str back. So for initializetest it will create a string from the allocated memory (by copying data) and throw the pointer away.

Now we're creating a new type, a POINTER to c_char. This is then used in both functions.

For Python, this type points to a single char so we have to cast it to get the whole string after searchtest is done. We cast to c_char_p because we just want to read the value so a const pointer is OK.

As a side note, this illustrates the disastrous effect of using c_char_p with functions that modify the array (as searchtest above does):

>>> libc.memset.argtypes = [c_char_p, c_int, c_int]
>>> foo = 'Python'
>>> foo
'Python'
>>> libc.memset(foo, ord('x'), 3)
44808532
>>> foo
'xxxhon'
>>>

Note how we've managed to change an immutable Python string!

The argtypes setup line isn't even needed because ctypes assumes c_char_p if Python str is used as argument.

2 of 2
1

Maybe by using restype like described here

class Test(object):
    def __init__(self):
        self.test_library=CDLL("./test.so")
        self.test_initialize = self.test_library.initializetest
        self.test_initialize.argtypes = []
        self.test_initialize.restype = c_char_p # c_char_p is a pointer to a string
        self.test_search = self.test_library.searchtest
        self.test_search.restype = c_int
        self.test_search.argtypes = [c_char_p]
        self.m = c_char_p(self.test_initialize())

    def search(self):
        return self.test_search(self.m).value

r = Test()
print r.search()

EDIT: corrected after test :)

🌐
Runebook.dev
runebook.dev › en › docs › python › library › ctypes › ctypes.c_char_p
Working with C Strings in Python: Tips for ctypes.c_char_p
October 23, 2025 - If you need a buffer that a C function can write back to (i.e., modify the string), a simple c_char_p initialized from a Python byte literal usually points to read-only memory in Python's internal structure. The best practice for a writable string buffer is to use ctypes.create_string_buffer().
Find elsewhere
🌐
BestDivision
bestdivision.com › spread your knowledge - bestdivision › questions - bestdivision › python questions - categories - bestdivision › how to convert a python string to c_char_p in ctypes? - bestdivision
How to convert a Python string to c_char_p in ctypes? | BestDivision
July 15, 2023 - Converting to c_char_p is necessary when interfacing with C libraries that expect string pointers. This conversion ensures that the Python string is correctly passed as a char * argument. Suppose you have a simple C library function that takes a string and prints it: To call this function from Python using ctypes, you can follow these steps:
🌐
Python
docs.python.org › 3 › library › ctypes.html
ctypes — A foreign function library for Python
When a foreign function is called, ... accepts. For example, a c_char_p item in the argtypes tuple will convert a string passed as argument into a bytes object using ctypes conversion rules....
🌐
Python.org
discuss.python.org › python help
Dealing with char*** in ctypes - Python Help - Discussions on Python.org
December 13, 2023 - I have this function in C library ... ctypes: static const char *names[] = {"Backplane", "ADC", "External", "Reserved"}; int test_char_ptr(const char ***names_, int *count_) { *names_ = names; *count_ = 4; return 0; } I can then ...
Top answer
1 of 2
8

There are a number of problems:

  1. Define .argtypes for your functions. It will catch errors passing incorrect parameters. Add the line below and note it is plural and is a tuple of argument types. The comma makes a 1-tuple:

python_p_printme.argtypes = c_char_p,

  1. Once you make that change, you'll get an error because this code:

    c_sends = pointer(c_char_p(CHAR.encode('utf-8')

is actually sending a C char** (a pointer to a c_char_p). Once you've set the argtypes properly, you can just call the function with a byte string and it will work. Your function becomes:

def printmeP(CHAR):
    print("In Print function")
    print(CHAR)
    python_p_printme(CHAR.encode())
    print("DONE function - Python")
  1. There is one more subtle problem. While the program may appear to work at this point Python strings are immutable so if the function being called requires a mutable string, you must allocate a mutable buffer using either create_unicode_buffer (for c_wchar_p) or create_string_buffer (for c_char_p); otherwise, the strcat in your C code is going to corrupt the Python string.

Here's a full example:

test.cpp

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// For Windows compatibility
#ifdef _WIN32
#   define API __declspec(dllexport)
#else
#   define API
#endif

// For C++ compiler compatibility
#ifdef __cplusplus
extern "C" {
#endif

API void alter_me(char* param, size_t length) {
    // truncates if additional info exceeds length
    strncat_s(param, length, " adding some info", length - 1);
}

#ifdef __cplusplus
}
#endif

test.py

from ctypes import *

lib = CDLL('./test')
alter_me = lib.alter_me
alter_me.argtypes = c_char_p,c_size_t
alter_me.restype = None

data = create_string_buffer(b'test',size=10)
alter_me(data,sizeof(data))
print(data.value)

data = create_string_buffer(b'test',size=50)
alter_me(data,sizeof(data))
print(data.value)

Output:

b'test addi'
b'test adding some info'

Note you do not need to use create_string_buffer if the C function does not alter the buffer, such as if the C parameter is const char*. Then you could just call printme(b'test string').

2 of 2
2

You could use create_string_buffer.

The documentation can be found here: https://docs.python.org/3/library/ctypes.html#ctypes.create_string_buffer

ctypes.create_string_buffer(init_or_size, size=None)

This function creates a mutable character buffer. The returned object is a ctypes array of c_char.

init_or_size must be an integer which specifies the size of the array, or a bytes object which will be used to initialize the array items.

With buf.value.decode("utf-8") you can convert the buffer back to a UTF-8 python string.

A small example with your C code library might look like this:

from ctypes import *

mylib_lib = cdll.LoadLibrary("<your-lib>")
mylib_lib.printme.argtypes = c_char_p,

buf = create_string_buffer(128)
buf.value = b'Hello World'
mylib_lib.printme(buf)
print("print on python side:", buf.value.decode("utf-8"))

It would output:

Start c Function!
Hello World
...
print on python side: Hello World!

on the console.

Top answer
1 of 1
26

c_char_p is a subclass of _SimpleCData, with _type_ == 'z'. The __init__ method calls the type's setfunc, which for simple type 'z' is z_set.

In Python 2, the z_set function (2.7.7) is written to handle both str and unicode strings. Prior to Python 3, str is an 8-bit string. CPython 2.x str internally uses a C null-terminated string (i.e. an array of bytes terminated by \0), for which z_set can call PyString_AS_STRING (i.e. get a pointer to the internal buffer of the str object). A unicode string needs to first be encoded to a byte string. z_set handles this encoding automatically and keeps a reference to the encoded string in the _objects attribute.

>>> c = u'spam'
>>> a = c_char_p(c)
>>> a._objects
'spam'
>>> type(a._objects)
<type 'str'>

On Windows, the default ctypes string encoding is 'mbcs', with error handling set to 'ignore'. On all other platforms the default encoding is 'ascii', with 'strict' error handling. To modify the default, call ctypes.set_conversion_mode. For example, set_conversion_mode('utf-8', 'strict').

In Python 3, the z_set function (3.4.1) does not automatically convert str (now Unicode) to bytes. The paradigm shifted in Python 3 to strictly divide character strings from binary data. The ctypes default conversions were removed, as was the function set_conversion_mode. You have to pass c_char_p a bytes object (e.g. b'spam' or 'spam'.encode('utf-8')). In CPython 3.x, z_set calls the C-API function PyBytes_AsString to get a pointer to the internal buffer of the bytes object.

Note that if the C function modifies the string, then you need to instead use create_string_buffer to create a c_char array. Look for a parameter to be typed as const to know that it's safe to use c_char_p.

🌐
GitHub
github.com › dmlc › nnvm › blob › master › python › nnvm › _base.py
nnvm/python/nnvm/_base.py at master · dmlc/nnvm
pass · · #---------------------------- # library loading · #---------------------------- if sys.version_info[0] == 3: string_types = str · numeric_types = (float, int, np.float32, np.int32) # this function is needed for python3 · # to convert ctypes.char_p .value back to python str ·
Author: dmlc
🌐
Numba Discussion
numba.discourse.group › community support
Accelerate loops that use ctypes, c_char_p, numpy str_? - Community Support - Numba Discussion
June 13, 2020 - I wrote a python library that wraps a c shared-library with over 600 functions using pure ctypes and numpy. The functions are typically simple, say given a string return a float, and for some functions I allow users to p…
🌐
GitHub
github.com › aquynh › capstone › issues › 557
Python 3 support: Bind `str` to `c_wchar_p` instead of `c_char_p` · Issue #557 · capstone-engine/capstone
December 1, 2015 - Cause: CsError's __str__ function returns a bytes (Python 2 non-unicode string) instead of a str (Python 3 unicode string). Python 3 requires that __str__ returns a str. Solution: When setting up the functions in __init__.py, use ctypes.c_wchar_p if it's Python 3. PS: There are also three other functions in __init__.py which return c_char_p.
Author: capstone-engine
🌐
Behaviour
behaviour.space › posts › 2021-03-28-ctypes-weird-and-inconvenient-typing.html
The weird and inconvenient typing of Python's ctypes library
March 28, 2021 - The library is so eager to support us, it starts doing type conversions without being asked. If a C-function has return type ctypes.c_wchar_p (and probably also ctypes.c_char_p but Python uses 16bit characters for strings) ctypes will handle the conversion to a Python str string automatically.