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 ファイルは動的 lib になりますfoolib.so

gcc -fPIC -shared -ofoolib.sofoolib.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)

変更前の出力 (2 番目の文字列のガベージは、ガベージ コレクションされたメモリへのアクセスを示し、したがって未定義の動作を示します):

21
xooiddfggggggggggggvd
♀ oxooiddfggggggggggggvd

変更後の出力:

21
xooiddfggggggggggggvd
iooxooiddfggggggggggggvd
于 2013-10-31T05:57:26.183 に答える
0

Python GC が を食べるためcreate_string_buffer(s)、まだsrc!

これに変更しても問題ありません:

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

c_void_p の代わりに c_char_p を使用する必要があるかもしれません。

于 2013-10-31T05:55:46.267 に答える