2016-07-26 7 views
1

次のCythonコードは期待どおりに機能しません。Cythonのヌル文字の問題

cdef char* char_tester(): 
    py_str = "a\0b\0c".encode("UTF-8") 
    cdef char* c_str = py_str 
    return c_str 

def test(): 
    print(char_tester()) 
    cdef char* my_str = char_tester() 
    for i in range(5): 
     print(my_str[i]) 

>>> test() 
b'a' 
97 
55 
10 
0 
99 

Iコードがその順序でバイト列 'bはC'、およびASCII値97、0、98、0、99、プリントアウトすることが期待されます。さらに、forループ内の文字を出力するforループを追加すると、出力として期待されるASCII値が得られます。どうやら、char_testerによって返されたchar*は、何とかtest()関数で切り捨てられています。これを防ぐにはどうしたらいいですか?

+0

あなたは[ドキュメント]を見ていました(http://docs.cython.org/enで

/latest/src/tutorial/strings.html)?私は、Python関数からC関数を呼び出すと、 'char *'をPython文字列に変換し、それをヌルで終了する文字列として扱うと仮定します。 – BrenBarn

+0

はい、私は行の中の変数の型を指定しました: cdef char * my_str = char_tester()、それは無関係であるべきです。 – Alex

答えて

2

対応cdef char * s = py_strは、char_tester()が返された後に無効なメモリ位置を指します。これは、C関数がローカルスタックに割り当てられた変数、未定義の振る舞いにアドレスを返す場合と似ています。テストコードが印刷されます

from libc.stdlib cimport malloc 
from libc.string cimport memcpy 

cdef char* char_tester(): 
    py_str = "a\0b\0c".encode("UTF-8") 
    cdef char* c_str 
    cdef char * s = py_str 
    cdef ssize_t slen = len(py_str) 

    c_str = <char *>malloc((slen+1)*sizeof(char)) 
    memcpy(c_str, s, slen) 
    c_str[slen] = '\0' 
    return c_str 

次の関数(のpython 3.4)

b'a' 
97 
0 
98 
0 
99 
+0

既に '\ 0'があるので、この場合はchar配列の末尾に余分な '\ 0'が必要ないでしょう。 –