Python ctypes设置c_char_p基础值

时间:2019-03-07 17:42:49

标签: python ctypes

我有一个指向结构的指针。在该结构内部,一个字段是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" 

这显示“仅在python端”。但是,正在查看bar的C进程无法获得反映的更改。

我该如何“管理” bar,以便对其进行设置,并且更改会在任何其他具有指向相同地址的指针的应用程序中得到体现?

2 个答案:

答案 0 :(得分:1)

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

  

但是,请注意不要将它们传递给期望指向可变内存的指针的函数。如果您需要可变的内存块,则ctypes具有create_string_buffer()函数,该函数可以通过各种方式创建这些内存块。

因此,您要执行以下操作:

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

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

答案 1 :(得分:1)

通过注释,您具有一个返回POINTER(foo)实例的函数。这是一个读取返回值并对其进行更改的工作示例。如果您的代码仍无法正常工作,请创建一个类似的示例来重现该问题:

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'