LoginSignup
0
0

More than 3 years have passed since last update.

備忘録 cpython Unicodeデータの入出力方法

Last updated at Posted at 2021-04-19

訳あって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作れないんだけど、、
}

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0