
| ■ | 実践Python拡張モジュールづくり (UNIX編) |
●ソースプログラムを書く
まずはソースプログラムを書きます。
前のページの例はあまりに簡単すぎて意味のないものだったので、
多少は「役に立つ」ものを作ってみましょうか?
#include "Python.h"
#include <ctype.h>
#include <string.h>
/* 引数は
* escaper.escape("string")
* escaper.escape("string", 進数(8 or 16)
* の2通りを可能とします。上の場合は16進数モードになります。
*/
static PyObject* escaper_escape(PyObject* self, PyObject* args){
int radi;
int i;
int srclen;
char* srcp;
PyObject* outobj;
/* 引数のデータ型「s#」は文字列本体とその長さの組を表します */
if(! PyArg_ParseTuple(args, "s#i", & srcp, & srclen, & radi)){
if(! PyArg_ParseTuple(args, "s#", & srcp, & srclen))
return NULL;
else
radi = 16;
}
if(radi != 8 && radi != 16){
PyErr_SetString(PyExc_AttributeError,
"radix parameter must be one of: 8, 16.");
return NULL;
}
{
char* p, * q, * resultp;
int i;
/* 元の文字列の最大4倍の長さになる可能性があります */
if((resultp = (char* )malloc(srclen * 4)) == NULL){
PyErr_SetString(PyExc_MemoryError, "Ootto! out of memory.");
return NULL;
}
for(i=0, p=srcp, q=resultp; i<srclen; i++){
if(isprint(*p))
*q++ = *p++;
else{
char tbuf[10], * r;
if(radi == 16){
sprintf(tbuf, "%02x", *p); *q++ = '\\'; *q++ = 'x';
}
else if(radi == 8){
sprintf(tbuf, "%03o", *p); *q++ = '\\';
}
for(r=tbuf; *r; *q++ = *r++) ;
p++;
}
}
*q = '\0';
outobj = Py_BuildValue("s", resultp);
free( (char* ) resultp );
return outobj;
}
}
static PyMethodDef defs[] = {
{"escape", escaper_escape, METH_VARARGS},
{NULL, NULL}
};
void initescaper(void){
Py_InitModule("escaper", defs);
}
/* end. */
|
このソースプログラムをコンパイルすると、 「escaper」というPythonモジュールを作ることができます。 そのescaperには「escape」という関数が1個含まれ、 escaper.escapeは渡された文字列に含まれる制御文字(非表示文字) を\x03などのエスケープ表記に変換して返します。8進か16進で選択できるので、
import escaper
a = escaper.escape('\x0a\x00\x75')
b = escaper.escape('\x0a\x00\x75', 8)
|
のように使うことができます。
ソースプログラムの説明は先述の通りです。引数の受け取り方、
エラー処理の仕方、戻り値の返し方それぞれ、
決まったPython APIを使えばいいので分かりやすいと思います。
void initescaper(void){
Py_InitModule("escaper", defs);
}
モジュールには固有のモジュール名が必要ですが、
それはこの初期化関数でPy_InitModuleを使って定義します。
ここではモジュールの名前を「escaper」にしていますが、
初期化関数の名前は、
必ず「init」+モジュール名に合わせないといけないことに注意が必要です。
またソースプログラムのファイル名は「escapermodule.c」としておきます。
*shared* escaper escapermodule.o # end.そして、Pythonのソース配布のMiscディレクトリから、「Makefile.pre.in」 というファイルをコピーしてきます。 Makefile.pre.in、Setup、それにescapermodule.cの3つがそろったら、 次の手順でビルドします。
% make -f Makefile.pre.in boot % makeescapermodule.so (HP-UXでは.sl)という共有ライブラリが無事にできれば大成功です。 このライブラリ名は固定です。つまり、 モジュール名+「module.so」(または.sl) という名前でなければいけません。
セクションのサブメニューに戻る
(first uploaded 2001/01/27 last updated 2002/07/20)