2016-03-24 27 views
1

私は、引数としてstrオブジェクトを受け入れるはずのC拡張関数を作成していました。python3 strオブジェクトはPyUnicode_Checkを渡すことができません

static PyObject *py_print_chars(PyObject *self, PyObject *o) { 
PyObject *bytes; 
char *s; 
if (!PyUnicode_Check(o)) { 
    PyErr_SetString(PyExc_TypeError, "Expected string"); 
    return NULL; 
} 
bytes = PyUnicode_AsUTF8String(o); 
s = PyBytes_AsString(bytes); 
print_chars(s); 
Py_DECREF(bytes); 
Py_RETURN_NONE; 
} 

しかし、私はのpython3コンソールでモジュールをテストとして、私はstrオブジェクトがPyUnicode_Checkを渡すことはできません見つける:コードを以下に示します

私の知る限りでは
>>> from sample2 import *  
>>> print_chars('Hello world')  
Traceback (most recent call last): 
File "<stdin>", line 1, in <module> 
TypeError: Expected string 

、Pythonの3のstr() typeはCでPyUnicodeと呼ばれ、上記のCコードは "python cookbook3" Char15.13を参照して書かれています。私は問題を解決できません。誰でも私のコードに何が間違っているのか教えてもらえますか?

何らかの理由で、あなたはPyObject *と直接作業しているとはPyArg_ParseTuple()を使用することができない場合は、次のコードサンプルは、あなたがチェックして抽出する方法を示しています。ここでは

は言った、「パイソンcookbook3」でありますバイト、文字列オブジェクトの両方から適当char *参照:

/* Some Python Object (obtained somehow) */ 
PyObject *obj; 

/* Conversion from bytes */ 
{ 
    char *s; 
    s = PyBytes_AsString(o); 
    if (!s) { 
     return NULL; /* TypeError already raised */ 
    } 
    print_chars(s); 
} 
/* Conversion to UTF-8 bytes from a string */ 
{ 
    PyObject *bytes; 
    char *s; 
    if (!PyUnicode_Check(obj)) { 
     PyErr_SetString(PyExc_TypeError, "Expected string"); 
     return NULL; 
    } 
    bytes = PyUnicode_AsUTF8String(obj); 
    s = PyBytes_AsString(bytes); 
    print_chars(s); 
    Py_DECREF(bytes); 
} 

全体コード:

#include "Python.h" 
#include "sample.h" 

static PyObject *py_print_chars(PyObject *self, PyObject *o) { 
    PyObject *bytes; 
    char *s; 
    if (!PyUnicode_Check(o)) { 
     PyErr_SetString(PyExc_TypeError, "Expected string"); 
     return NULL; 
    } 
    bytes = PyUnicode_AsUTF8String(o); 
    s = PyBytes_AsString(bytes); 
    print_chars(s); 
    Py_DECREF(bytes); 
    Py_RETURN_NONE; 
} 

/* Module method table */ 
static PyMethodDef SampleMethods[] = { 
    {"print_chars", py_print_chars, METH_VARARGS, "print character"}, 
    { NULL, NULL, 0, NULL} 
}; 

/* Module structure */ 
static struct PyModuleDef samplemodule = { 
PyModuleDef_HEAD_INIT, 
    "sample", 
    "A sample module", 
    -1, 
    SampleMethods 
}; 

/* Module initialization function */ 
PyMODINIT_FUNC 
PyInit_sample2(void) { 
    return PyModule_Create(&samplemodule); 
} 
+0

'' PyArg_ParseTuple'に 'u'の引数を先に入れる必要はありませんか?しかし、METH_VARARGSのようなメソッドテーブルの引数の型に依存します。 – cdarke

+0

はい、事実上、PyArg_parseTupelはこの問題を完全にスローすることができます。しかし、 "python cookbook3"には、PyArg_ParseTupleを使わずに別のワークアウトがあると言われています。 – sun

+0

私は、コードの他の部分が、他のファンクションでうまく機能しているため間違っているかもしれないとは考えていませんでした。質問の説明にコード全体を追加しています。 – sun

答えて

3

目的が1つの引数を正確に受け入れることである場合は、should be declared as METH_Oではなく、METH_VARARGSです。前者はラップせずに単一の引数に従います。後者はtupleにラップされます。tupleは、内部にPyUnicode*を得るために解凍または解析する必要があります。

+0

ありがとうございます、あなたはポイントを打つ。 – sun

関連する問題