歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Python調用C模塊(一):C api方式

Python調用C模塊(一):C api方式

日期:2017/3/1 10:29:43   编辑:Linux編程
接前面 Python與C相互調用(見 http://www.linuxidc.com/Linux/2012-02/55040.htm ),繼續一點一點學習,順便記錄下筆記。

大致計劃如下(測試平台僅限於Windows 和 Linux,編譯器限於 MSVC、Mingw及linux gcc):

  • 傳統方式調用 C 模塊
  • 用 ctypes 調用C動態庫
  • 如有精力和興趣,簡單熟悉一下swig、boost.python, sip, shiboken
  • 用 C 調用 Python

如果只是簡單地調用系統調用或c函數,應該考慮使用ctypes。但傳統方式更通用,比如C模塊中同時要調用python。

簡單例子

示例代碼

//hellomodule.c
#include <Python.h>
#include <string.h>

static PyObject * message(PyObject *self, PyObject *args)
{
char *src, res[100];
if (! PyArg_Parse(args, "(s)", &src))
{
return NULL;
}
else
{
strcpy(res, "Hello, ");
strcat(res, src);
return Py_BuildValue("s", res);
}
}

static struct PyMethodDef methods[] =
{
//導出到Python中的名字、函數指針,參數類型,函數描述
{"message", message, 1, "descript of message"},
//結束
{NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC inithello()
{
// 導出的模塊名,前面結構數組的指針
(void) Py_InitModule("hello", methods);
}
  • 先定義一個函數,函數的參數和返回值都是 PyObject* 類型。(函數內需要將其轉成C語言的類型,最後轉成PyObject* 類型返回)

  • 定義一個結構數組,包含我們模塊內函數的信息
  • 定義一個 init 函數,該函數在模塊被導入時執行。前面的 PyMODINIT 隱藏windows下 __declspec(dllexport)這個東西

編譯

  • 用 msvc 編譯

cl /LD hellomodule.c /ID:\python26\include /LIBPATH:D:\python26\libs D:\python26\libs\python26.lib /ohello.pyd
  • 用 mingw 編譯

gcc hellomodule.c -shared -ID:\Python26\include -LD:\Python26\libs -lpython26 -o hello.pyd
  • linux 下編譯

gcc -shared hellomodule.c -I/usr/include/python2.6  -ohello.so -L/usr/lib/python2.6 -lpython2.6
  • 采用distutils方式

前面都是直接調用編譯器來生成C模塊,有時輸這麼多命令總是不太方便。幸好,Python 在這方面提供了一個工具。 我們只需要編寫一個簡單的Python文件:

#setup.py
from distutils.core import setup, Extension
example_mod = Extension('hello', sources = ['hellomodule.c'])
setup(name = "hello",
version = "1.0",
description = "A sample extension module",
ext_modules = [example_mod], #setup()中,只有這行是必須的
)

然後執行

python setup.py build

即可。

也可以直接執行

python setup.py install

將模塊安裝到Python路徑下

測試運行

import hello
print hello.message("OK")

備忘:小插曲,采用msvc編譯後,運行時始終找不到 message 函數。最終發現和注釋中有中文有關(可能是和unix的換行符結合使用的問題),細節部分序進一步試驗。

重新審視例子

  • 包含 #include <Python.h>

  • 方法函數(主角) PyObject* func(PyObject* self, PyObject * args)

  • 結構數組 (包含函數信息)
  • 模塊初始化函數 (注冊結構數組)
Copyright © Linux教程網 All Rights Reserved