Python呼叫C/C++方式

NickZhou發表於2019-02-16

Python呼叫C++方式

方式一(基礎篇)

這種方法叫做python的擴充套件

int great_function(int a) {
    return a + 1;
}

使用python這樣呼叫

>>> from great_module import great_function 
>>> great_function(2)
3
// great_module.c

// 引用python的標頭檔案
#include <Python.h>

int great_function(int a) {
    return a + 1;
}

// 包裹函式,用來包裹需要轉化為python的函式,在方法前面加下劃線。
static PyObject * _great_function(PyObject *self, PyObject *args)
{
    int _a;
    int res;

    // 檢查引數型別是否正確,python引數轉化為c
    if (!PyArg_ParseTuple(args, "i", &_a))
        return NULL;
    res = great_function(_a);
    return PyLong_FromLong(res);
}

// 定義的方法表,用於在python中查詢
static PyMethodDef GreateModuleMethods[] = {
    {
        "great_function",
        _great_function,
        METH_VARARGS,
        ""
    },
    {NULL, NULL, 0, NULL}
};

// 必須以module名前面加init定義該方法
PyMODINIT_FUNC initgreat_module(void) {
    (void) Py_InitModule("great_module", GreateModuleMethods);
}

在Linux下面,則用gcc編譯:

$ gcc -fPIC -shared great_module.c -o great_module.so -I/usr/include/python2.7/ -lpython2.7

gcc命令列引數

  • -shared

    • 生成一個共享物件,可以與其他物件接連成可執行檔案
  • -fPIC

    • 適用於動態連結,避免全域性偏移表大小的限制,只能在某些機器上執行

在當前目錄下得到great_module.so,同理可以在Python中直接使用。

方法二(使用SWIG)

SWIG : Simplified Wrapper and Interface Generator

呼叫c

不僅可以用於python,也可以用於其他java/perl/ruby/php/JavaScript/Go。

/* great_module.i */
%module great_module
%{
int great_function(int a) {
    return a + 1;
}
%}
int great_function(int a);
  1. 定義module名稱通常和檔名保持一致。
  2. %{%}包裹的部分是c語言程式碼,這段程式碼會原封不動的複製到mymodule_wrap.c
  3. 欲匯出的函式簽名列表。直接從標頭檔案中複製過來即可
$ swig -c++ -python great_module.i

會生成對應的great_module_wrap.cgreat_module.py檔案

再執行:

$ g++ -fPIC -shared great_class_wrap.cxx -o _great_class.so  -I/usr/include/python2.7/ -lpython2.7

生成對應的_great_module.so檔案,這時,我們就可以再python中直接呼叫了

from great_module import great_function

print great_function(9)

>>> 10

呼叫c++

定義一個標頭檔案,great_class.h

#ifndef GREAT_CLASS
#define GREAT_CLASS
class Great {
    private:
        int s;

    public:
        void setWall (int _s) {s = _s;};
        int getWall() {return s;};
};
#endif

再定義一個great_class.i的swig配置檔案,這裡不用再寫一遍SWIG的定義了,直接使用SWIG的%include指令;
在SWIG編譯時要加-c++這個選項,生成的副檔名為cxx

/* great_class.h */

%module great_class
%{
#include "great_class.h"
%}
%include "great_class.h"

執行命令:

$ swig -c++ -python great_class.i

在Linux下,使用C++編譯器g++

g++ -fPIC -shared great_class_wrap.cxx -o _great_class.so  -I/usr/include/python2.7/ -lpython2.7

生成對應的_great_class.so檔案。現在可以直接在python中輸入

import great_class
c = great_class.Great()
c.setWall(10)
print c.getWall()

>>> 10

參考

相關文章