pythonからC言語を利用する(2)

前回の続きで、Cでshared object(動的ライブラリ)を作成するところと含めて以下の順番で試してみた。
(1)Cで動くプログラムの作成
(2)Cの共有ライブラリの作成
(3)pythonからCの共有ライブラリをロードする
(4)pythonからCの関数を実行する

共有ライブラリの作成に当たっては、以下のサイトを参考にさせていただきました。

[c]gccを用いたCの共有ライブラリの作り方
http://d.hatena.ne.jp/sleepy_yoshi/20090510/p1

なお、以下の開発/動作環境はLinux(Ubuntu10.04)です。

Cで動くプログラムの作成

まず、Cで動く簡単なプログラムを作ってみた。
後々ライブラリとして使う、forlib.cとforlib.hと、それを動かすmain関数のforlib_main.cを用意した。

  • forlib.h
#ifndef FORLIB_H
#define FORLIB_H

void print_hoge(int num);

#endif // end of FORLIB_H  
  • forlib.c
include <stdio.h>
#include "forlib.h"

void print_hoge(int num)
{
        int i;
	for (i=0; i<num; i++) {
		printf("hoge:%d\n",i);
	}

}
  • forlib_main.c
#include "forlib.h"

int main(void)
{
        print_hoge(10);
}


まずは、普通にCのプログラムをbuildして動かしてみる。

$ gcc forlib_main.c forlib.c -o forlib
$ ./forlib 
hoge:0
hoge:1
hoge:2
hoge:3
hoge:4
hoge:5
hoge:6
hoge:7
hoge:8
hoge:9

動いた。

共有ライブラリの作成

続いて、shared object(shared library, dynamic link library)を作る。
"-shared"を指定することで出来る。

$ gcc -shared forlib.c -o libforlib.so
$ ls -a libforlib.so 
libforlib.so

できた。

pythonからCの共有ライブラリのロード、実行

pythonから先に作成した共有ライブラリをロード、実行してみる。

$ python
Python 2.6.6 (r266:84292, Sep 15 2010, 15:52:39) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import ctypes
>>> PATH_TO_LIB = './libforlib.so'
>>> lib = ctypes.cdll.LoadLibrary(PATH_TO_LIB)
>>> lib.print_hoge(5)
hoge:0
hoge:1
hoge:2
hoge:3
hoge:4
5
>>> 

ということで、めでたく出来た。

余談

今回調べるまで、静的なライブラリ(gcc環境だと*.aのようなもの)でも、当初出来るかもと思っていたが、出来なかった。
静的なライブラリの場合、リンクされていない状態なので、python側でリンカを用意しない限り使えないとのこと。
一方、動的ライブラリの場合、ロード可能な実行可能オブジェクトになっているため、ローダを用意すれば使えるとのことらしい。
下記参照。

静的/動的リンクライブラリについて
http://okwave.jp/qa/q6809861.html