訳あってPython CAPIを使い始めたが、C言語、C++初心者のため悪戦苦闘中。
ただし初心者でもわかるぐらいpython3系のUnicodeAPIは、
とっ散らかっている。おそらく過渡期なんだとCpythonのソースから感じた。
単にUnicodeオブジェクトの読み書きをしたいだけなのだが、
どうもExampleが見当たらない。備忘録として残しておく。
Cへの入力(PyObjectを読込む)
python2系
PyObject* o = xxxx;
if (PyUnicode_Check(o))
return NULL;
Py_UNICODE* u = PyUnicode_AsUnicode(o);
// uはC言語で扱えるデータ
ここまでは分かりやすかったのだが、3分の2は廃止予定の関数、、
python3系
どんだけ2系と違うんだよ。。
パターン1
きっツ
PyObject* o = xxxxx;
if (PyUnicode_READY(o) == -1)
return NULL;
void *data = PyUnicode_DATA(o);
int kind = PyUnicode_KIND(o);
Py_ssize_t len = PyUnicode_GET_LENGTH(o);
Py_UCS4* u = new Py_UCS4[len+1]; // C++ならこうか?
// Py_UCS4* u = (Py_UCS4*)calloc((len+1)*sizeof(Py_UCS4)); // Cならこうか?
for (Py_ssize_t i = 0; i < len; i++) {
u[i] = PyUnicode_READ(kind, data, i);
}
//メモリ開放忘れるととんでもないことに
delete[] u;
// free(u);
パターン2
ソースを見る限りこういう技もあるようだがやってよいのか?
PyObject* o = xxxxx;
if (PyUnicode_READY(o) == -1)
return NULL;
int kind = PyUnicode_KIND(o);
void *data = PyUnicode_DATA(o);
if (kind == PyUnicode_1BYTE_KIND)
Py_UCS1 *s = (Py_UCS1 *)data;
elif (kind == PyUnicode_2BYTE_KIND)
Py_UCS2 *s = (Py_UCS2 *)data;
else
Py_UCS4 *s = (Py_UCS4 *)data;
Py_UCS4* u = (Py_UCS4 *)s;
// uはC言語で扱えるデータ
うーん
// さらに枝狩りして以下と同じかと
PyObject* o = xxxxx;
if (PyUnicode_READY(o) == -1)
return NULL;
void *data = PyUnicode_DATA(o);
Py_UCS4* u = (Py_UCS4 *)data;
うーん直感的に何やってるのかわからない。
パターン3
これに落ち着いた。
PyObject *orgpy;//<-インプット
Py_ssize_t len =PyObject_Length(orgpy);
Py_UCS4 u;
for (Py_ssize_t i = 0; i < len; i++)
{
u = PyUnicode_READ_CHAR(orgpy, i);
//何か処理
}
迷走の理由
https://docs.python.org/ja/3/c-api/unicode.html
この説明だけ見て使える人ってどれだけいるの?
使い方を知りたいだけなのに例がないため、中途半端な説明のおかげで大混乱。
ソースを読み、デバッグしながらでようやく理解できたレベルで腹立たしい。
pyへの出力(PyObjectを書き出す)
マルチバイト系の取り扱い方法がまだ全く分かってない。
python2系
const char *ascii = "hoge";
PyObject* o = PyUnicode_FromString(ascii);
// oはpythonから見えるオブジェクト
const Py_UNICODE *u; //<-マルチバイトだとする
Py_ssize_t size = 1; //<- たぶん文字数?未確認
PyObject* o = PyUnicode_FromUnicode(u, size)
python3系
uだけあっても書き込めない!?
謎過ぎてあってるのかどうかすらわかない。
PyObject *py;
Py_UCS1 *data = PyUnicode_1BYTE_DATA(orgpy); //<-これ1byte大事
int kind = PyUnicode_KIND(orgpy); //<-でもKINDは1とは限らない //kind情報がわかってないといけないということは元となるPyObjectがないとはっきりとわからないのでは?
Py_ssize_t len = zz; //あらかじめdataの長さがわかってないといけない。
// uの長さってどうやったら調べられるの?
for (Py_ssize_t i = 0; i < len; i++)
{
py = PyUnicode_FromKindAndData(kind, data + (i * kind), 1);
// 何か処理!っていうか1文字単位でしかPyObject作れないんだけど、、
}