Python ctypes 设置 c_char_p 基础值

Python ctypes set c_char_p underlying value

我有一个指向结构的指针。在该结构中,其中一个字段是 POINTER(c_char)。我正在尝试设置基础值,以便更改会反映在任何其他具有指向相同地址的指针的应用程序中。

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" 

这表明 "only on the python side"。但是,正在查看 bar 的 C 进程不会得到反映的更改。

我怎样才能 "manage" bar 以便我可以设置它,并且该更改会反映在任何其他具有指向同一地址的指针的应用程序中?

您需要按照文档中的说明使用 create_string_buffer

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.

因此,在您的情况下,您需要执行以下操作:

z.contents.bar = create_string_buffer(b"My string", 10)

这将 bar 指向新缓冲区,然后您应该可以通过 .value 更改内容。 对于 Unicode (c_wchar),使用 create_unicode_buffer.

根据评论,您有一个 return 是 POINTER(foo) 实例的函数。这是读取 return 值并更改它的工作示例。如果您的代码仍然无法正常工作,请创建一个重现该问题的类似示例:

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)

输出:

b'abcdefghijklmnop'
b'abcd'