2

我正在学习如何通过以下示例使用 ctypes,但发生了奇怪的问题..

c文件在这里:

typedef struct post {
    char *x;
    char *y;
    int x_z;
} post_t;


void
foo (post_t *o, char *src)
{
    int i=0;

    char *p = src;
    int len = strlen(src);

    for (; *p != '\0'; i++, p++) {
        if (*p == 'x') {
            o->x = p;
            o->x_z = len-i;
        }
    }
    o->y=src;
}

python代码在这里(test.oy):

from ctypes import *

foolib = CDLL("./foolib.so")

class Post(Structure):
    _fields_ = (
        ("x", c_void_p),
        ("y", c_void_p),
        ("x_z", c_int),
    )

o = Post()

s = "iooxooiddfggggggggggggvd"

foolib.foo(byref(o), create_string_buffer(s))

print o.x_z

print string_at(o.x, o.x_z)
print string_at(o.y, len(s))

该结构post映射到 python class。C 文件将是一个动态库foolib.so

gcc -fPIC -shared -o傻瓜.so傻瓜.c

但是,奇怪的是,当我运行时python test.py,我得到了以下输出:

21
ooiddfggggggggggggvd
ooiddfggggggggggggvd

string_at(o.y, len(s))除外iooxooiddfggggggggggggvd

我的代码哪里出了问题?谢谢。

顺便说一句,为了快速测试它,我把代码放在 gist 上:https ://gist.github.com/hit9/7244344

4

3 回答 3

2

create_string_buffer(s)生成一个临时字符串,在函数调用后被垃圾收集。只需传递实际的字符串,因为您不修改它:

s = "iooxooiddfggggggggggggvd"
foolib.foo(byref(o), s)

更改前的输出(第二个字符串中的垃圾表示访问垃圾收集的内存,因此行为未定义):

21
xooiddfggggggggggggvd
♀ oxooiddfggggggggggggvd

更改后的输出:

21
xooiddfggggggggggggvd
iooxooiddfggggggggggggvd
于 2013-10-31T05:57:26.183 回答
0

因为 Python GC 吃掉了create_string_buffer(s),还没呢src

改成这样就OK了:

buf = create_string_buffer(s)
foolib.foo(byref(o), buf)
于 2013-10-31T05:50:56.367 回答
0

可能你应该使用 c_char_p 而不是 c_void_p。

于 2013-10-31T05:55:46.267 回答