Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python ctypes set c_char_p underlying value

Tags:

python

ctypes

I have a pointer to a struct. Inside that struct, one of the fields is a POINTER(c_char). I am trying to set the underlying value, so that the change is reflected in any other application with a pointer to the same address.

class foo(Structure):
    _fields_ = [("bar", POINTER(c_char)),
                 ("bazaz" c_int),
                 ...morefields]

z = .... # z is a pointer to a foo

# legal but doesn't do what I expect, this seems to set the pointer itself, not the underlying contents
z.contents.bar = b"asdfasdf" 

This shows "only on the python side". However, a C process that is looking at bar does not get the reflected change.

How can I "manage" bar so that I can set it, and that change is reflected in any other application with a pointer to the same address?

like image 451
Tommy Avatar asked Mar 16 '26 10:03

Tommy


1 Answers

From comments, you have a function that returns a POINTER(foo) instance. Here's a working example of reading the return value and changing it. If your code is still not working, create a similar example reproducing the issue:

test.c

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

struct foo
{
    char* bar;
};

__declspec(dllexport) struct foo* func()
{
    /* This leaks memory, but is just an example... */
    struct foo* f = malloc(sizeof(struct foo));
    f->bar = malloc(20);
    strcpy(f->bar,"abcdefghijklmnop");
    return f;
}

test.py

from ctypes import *

class foo(Structure):
    _fields_ = ('bar',c_char_p),

dll = CDLL('test')
dll.func.argtypes = ()
dll.func.restype = POINTER(foo)

f = dll.func()
print(f.contents.bar)
f.contents.bar = b'abcd'
print(f.contents.bar)

Output:

b'abcdefghijklmnop'
b'abcd'
like image 193
Mark Tolonen Avatar answered Mar 18 '26 00:03

Mark Tolonen