作成日
2018/06/04最終更新
2021/08/02記事区分
一般公開FFI (Foreign Function Interface) の一つである ctypes を利用すると、C 言語のライブラリを Python から利用できます。サンプルコードを記載します。
libm の sqrt を利用する例
main.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
from ctypes import CDLL, c_double
from ctypes.util import find_library
def Main():
libm = CDLL(find_library('m'), use_errno = True)
libm.sqrt.argtypes = [c_double]
libm.sqrt.restype = c_double
print libm.sqrt(121)
if __name__ == '__main__':
Main()
実行例
$ python main.py
11.0
libc 経由でシステムコールを利用する例
システムコールは libc 経由で利用できます。例えば、poll を Python から libc 経由で利用する例は以下のようになります。
main.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
from ctypes import CDLL, Structure, POINTER, c_short, c_int
from ctypes.util import find_library
class Pollfd(Structure):
# $ man 2 poll
# struct pollfd {
# int fd; /* file descriptor */
# short events; /* requested events */
# short revents; /* returned events */
# };
_fields_ = [("fd", c_int),
("events", c_short),
("revents", c_short)]
def _init_(self, fd, events, revents):
self.fd = fd
self.events = events
self.revents = revents
OnePollfdArrayType = Pollfd * 1
POLLIN = 0x0001 # https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/poll.h
POLLERR = 0x0008
POLLHUP = 0x0010
POLLNVAL = 0x0020
def Main():
libc = CDLL(find_library('c'), use_errno = True)
# ファイルディスクリプタ 0 を監視
fds = OnePollfdArrayType(Pollfd())
fds[0].fd = 0
fds[0].events = POLLIN
# C 言語の型を引数と返り値に関して設定
# $ man 2 poll
# int poll(struct pollfd *fds, nfds_t nfds, int timeout);
libc.poll.argtypes = [POINTER(Pollfd), c_int, c_int]
libc.poll.restype = c_int
while True:
n = libc.poll(fds, 1, 5000)
if n < 0:
raise Exception("poll")
elif n == 0:
print "no input"
else:
for ifd in range(1):
if fds[ifd].revents & (POLLERR | POLLHUP | POLLNVAL):
raise Exception("poll %d" % ifd)
elif fds[ifd].revents & POLLIN:
print "input from fd%d: %s" % (ifd, raw_input())
if __name__ == '__main__':
Main()
実行例
$ python main.py
aaa ←エンター
input from fd0: aaa
xxx
input from fd0: xxx
no input ←5秒経過
no input
その他の連携方法
C/C++ 動的ライブラリを Python から利用する方法としては ctypes 以外にも Python 標準の <Python.h> や Boost.Python があります。
例えば ModernGLでは libGL.so.1
を C++ 側で読み込むために <Python.h> が利用されています。OpenRAVE では Boost.Python が利用されています。
hello.cpp
#include <boost/python.hpp>
char const* greet() {
return "hello, world";
}
BOOST_PYTHON_MODULE(hello) {
using namespace boost::python;
def("greet", greet);
}
ldconfig で動的リンク対象のライブラリがインストールされていることを確認します。
/sbin/ldconfig -p | grep python
dpkg -S /usr/lib/x86_64-linux-gnu/libboost_python.so #=> libboost-python1.62-dev
dpkg -S /usr/lib/x86_64-linux-gnu/libpython2.7.so #=> libpython2.7-dev
ビルドコマンド例
g++ -shared -fPIC -lboost_python -lpython2.7 -I/usr/include/python2.7 -o hello.so hello.cpp
実行例
In [1]: import hello
In [2]: hello.greet()
Out[2]: 'hello, world'
関連記事
- cmake で ccache を有効化するための設定YOCTO Linux で開発している場合など、ビルド速度が開発効率にそのまま影響する際は ccache (compiler cache) で C/C++ ビルドを高速化することを考えます。cmakeと併用する場合の設定およびコマンド例を記載します。 インストール sudo apt install ccache 以下のバイナリファイルに加えて $ w
- 低レイヤーネットワークプログラミングに関する雑多な知識TCP/IP モデルのうちトランスポート層ではなく、インターネット層およびネットワークインターフェイス層のパケット (正確には PDU) を扱う低レイヤープログラミングの雑多なテクニックをまとめます。『ルーター自作でわかるパケットの流れ』などを参考にしています。バックアップ目的で書籍のサンプルコードをホスティングしました。 検証環境
- ファイルディスクリプタ関連のシステムコールのサンプルコード (C 言語)ファイル記述子 (File Descriptor) に関連するシステムコールを利用した C 言語のサンプルコードを記載します。 ファイルの読み書き open/close main.c #include <unistd.h> #include <fcntl.h> #include <stdio.h> int main() { int fd_r, fd_w;...
- C言語の資産を利用 (C++をもう一度)サンプルコード メルセンヌ・ツイスタなど、C言語で記述されたライブラリをC++から利用するためには extern "C" を利用します。その際、組み込みマクロ __cplusplus を利用するとC言語からもC++からも利用できるヘッダファイルを作成できます。 sub.h #ifndef SUB_H_ #define SUB_H_ #ifdef __cplu
- C言語コード読解:size_t型とはサイズを表現するための符号なし整数型です。読み手にとっても、何らかのサイズを格納するための変数であることが分かりやすくなります。真偽値をbool型変数で扱う場合も同様です。 sample.cpp #include <iostream> using namespace std; int main() { size_t size = sizeof(int); cout &l...