osx:10.12 g++ 7.1 swig 3.0.12 opencv 3.2.0
SWIG是Simplified Wrapper and Interface Generator的縮寫。是Python中調用C代碼的另一種方法。在這個方法中,開發人員必須編寫一個額外的接口文件來作為SWIG(終端工具)的入口
SWIG在官網上有很詳細的例子這里就只針對opencv進行講述
安裝SWIG
brew install swig
這里用一個小例子來先簡單介紹SWIG
//example.hpp
#ifndef example_hpp
#define example_hpp
#include <iostream>
#include <vector>
class Test{
public:
Test(){
for(int i=0;i<10;i++) v.push_back(i);
}
void see();
private:
std::vector<int> v;
};
#endif
//example.cpp
#include "example.hpp"
#include <stdio.h>
using namespace std;
void Test::see(){
for(int i=0;i<(this->v).size();i++)
printf("%d ",v[i]);
}
如何將這個類以及這個類的方法放在python里面調用呢
1.編寫轉換規則 example.i(接口文件)
%module example
%include "std_vector.i"
%{
#include "example.hpp"
%}
%include "example.hpp"
第一行 %module后面的名字是被封裝的模塊名稱,Python通過這個名稱來加載程序。
第二行是文件所以依賴的頭文件,vector本是STL里面的,但是SWIG已經有對應的"std_vector.i"寫好了,所以可以直接%include "std_vector.i"
,如果在python里面需要用到vector的話,在轉換規則里面還要添加模版類型,具體參考SWIG的DOC http://www.swig.org/Doc1.3/Library.html
大括號里面所添加的內容,一般包含此文件需要的一些函數聲明和頭文件。
最后一行是聲明了要封裝的函數和變量,因為函數聲明寫在了頭文件里面,如果全部封裝的話可以直接%include 頭文件名
2.封裝代碼,生成中間文件
swig -python -c++ example.i
這樣會生成兩個文件
example.cxx
,example.py
example.cxx :編譯c++時用
example.py:python import包時使用
3.使用distutils工具或命令編譯
"""
setup.py
"""
from distutils.core import setup,Extension
setup(name = "example",
version = "1.0",
ext_modules = [Extension("_example", ["example_wrap.cxx", "example.cpp"],
extra_compile_args = ['-std=c++11'])],
py_modules=['example'])
sudo python setup.py install
注意模塊名稱那里一定前面要加下划線
這會將生成的_example.so 和 example.py 送到python對應的package文件夾里
額外的參數和額外的庫都跟着需要更改
4.Python引用
In [1]: from example import *
In [2]: x = Test()
In [3]: x.see()
0 1 2 3 4 5 6 7 8 9
注意的問題:
c++中聲明的方法必須實現
GCC版本要和Python的底層版本一樣
在編寫接口文件的時候,需要將依賴的頭文件都添加進來,而opencv里面的文件繁多,在Github上面有人已經寫好了opencv.i
安裝方法:
沒什么安裝方法。。。下載文件直接將lib里面的文件復制到你Code的文件夾下面就好了。
使用方法在主頁上有介紹
需要注意的是在寫接口文件的時候,如果需要自己定義vector在python里面的接口,會出現redefinition的問題,因為作者寫的借口文件里面已經實現過了vector的接口,不需要寫,其他的STL類沒有試過,出現redefinition時估計也是一樣的問題。
作者沒有寫文檔,在調用接口的時候需要去查作者的test,比如opencv里面的
cv::Mat ,在封裝成python之后需要調用作者的module_name.Mat.from_array(img)
轉換成cv::Mat
參考文檔:
http://blog.csdn.net/jiangpeng59/article/details/73554835
http://cering.github.io/2015/12/08/使用SWIG實現Python調用C-C-代碼/
https://github.com/renatoGarcia/opencv-swig