2009年10月26日月曜日

C言語で書いた関数をPythonで使う

まずはC言語のプログラムを書く
/home/yoshi/python/cfunc.c
#include <Python.h>

static PyObject *cprint(PyObject *self, PyObject *args) {
    char *s;
    if(!PyArg_ParseTuple(args, "s", &s)) {
        return NULL;
    }
    printf(s, "");
    return Py_None;
}

static PyObject *add(PyObject *self, PyObject *args) {
    int i1, i2;
    if(!PyArg_ParseTuple(args, "ii", &i1, &i2)) {
        return NULL;
    }
    return Py_BuildValue("i", i1 + i2);
}

static PyObject *get_list(PyObject *self, PyObject *args) {
    PyObject *list;
    int i, n;
    if(!PyArg_ParseTuple(args, "i", &n)) {
        return NULL;
    }
    list = PyList_New(0);
    for(i = 0; i < n; i++) {
        PyList_Append(list, PyInt_FromLong(i));
    }
    return list;
}

/* メソッドテーブル */
static PyMethodDef methods[] = {
    {"cprint", cprint, METH_VARARGS, "cprint(str)"},
    {"add", add, METH_VARARGS, "int add(int, int)"},
    {"get_list", get_list, METH_VARARGS, "list get_list(int)"},
    {NULL, NULL, 0, NULL}
};

/*
初期化関数
変数名initcfuncはinitのあとに任意の名前をつける
この場合 cfunc なので initcfunc になる
*/
PyMODINIT_FUNC initcfunc(void) {
    (void) Py_InitModule("cfunc", methods);
}

cfunc.cをコンパイルするのに
Pythonのdistutilsパッケージを使いプログラムを書く
/home/yoshi/python/setup.py
from distutils.core import setup, Extension

module1 = Extension("cfunc", sources=["cfunc.c"])

setup(name='cfunc', version='1.0',
      description='This is a demo package',
      ext_modules=[module1])

ディレクトリを移動する
$ cd /home/yoshi/python
setup.pyを実行しcfunc.cをコンパイルする
$ python setup.py build

2つのファイルが生成される
1. /home/yoshi/python/build/lib.linux-i686-2.6/cfunc.so
2. /home/yoshi/python/build/temp.linux-i686-2.6/cfunc.o

cfunc.soを/home/yoshi/pythonディレクトリにコピーする

使ってみる
/home/yoshi/python/test.py
import cfunc

cfunc.cprint("hello\n")
print cfunc.add(1, 2)
print cfunc.get_list(10)

print cfunc.cprint.__doc__
print cfunc.add.__doc__
print cfunc.get_list.__doc__

実行すると
hello
3
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
cprint(str)
int add(int, int)
list get_list(int)

詳細はドキュメントで

0 件のコメント:

コメントを投稿