最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python 調用C++封裝的進一步探索交流

 更新時間:2021年03月04日 11:18:46   作者:purgle  
這篇文章主要介紹了Python 調用C++封裝的進一步探索交流,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

我們知道,C++和python各有優(yōu)缺點,C++可以直接映射到硬件底層,實現(xiàn)高效運行,而python能夠方便地來進行編程,有助于工程的快速實現(xiàn)。

那能不能發(fā)揮兩者的優(yōu)勢將它們結合起來?當然是可以的!有多種方法可以實現(xiàn)它們之間的相互轉換。

鏈接文章中,有提到一個簡單的例子,來教我們如何生成可以被python加載的文件。

但是這只能針對簡單的數(shù)據進行封裝,一旦涉及到自定義的類等封裝數(shù)據,就需要借助第三方庫來幫助更好實現(xiàn)。

比如numpy與C++的數(shù)據接口。

這里對python調用C++生成的pyd(so/dll)文件進行進一步的探索。

1.首先進行如下配置,在VC++目錄中包含python和numpy的文件目錄:

配置為Release平臺,不然numpy的頭文件無法被包含,導致編譯器鏈接出錯。

特別要注意的一點是用cmd生成pyd文件時,VS2013可能要輸入: SET VS90COMNTOOLS=%VS120COMNTOOLS%(每次重新打開cmd窗口運行pythonsetup.py build的時候都要輸入一次)才能生成成功。

2.理解python調用C++的數(shù)據交互過程:

Python中的代碼通過CPython等將語句解釋為C/C++語言,然后編譯器調用binding入口函數(shù),將傳進來的PyObject*參數(shù)通過PyFloat_AsDouble()等轉換成C/C++變量。

這些作為輸入變量傳進已經寫好的C++函數(shù),調用該函數(shù),返回C++結果。最后反過來,將C/C++變量轉成CPython可以識別的PyObject*對象返回給python編譯器(如函數(shù)PyFloat_FromDouble()),完成python到C++的調用。

當C/C++里面的輸入變量或者返回值都不是基本類型時,比如自定義的類,那我們同樣要按照類里面定義數(shù)據的方式以數(shù)據的方式來對應改成python能識別的基本類型的組合。

以Mat和numpy的array對象相互轉換為例:

//以Mat的allocator作為基類,Numpy的Allocator作為繼承類
//這樣可以用派生對象指針對基類數(shù)據進行操作
class NumpyAllocator : public MatAllocator
{
public:
 NumpyAllocator() { stdAllocator = Mat::getStdAllocator(); }
 ~NumpyAllocator() {}
 
 UMatData* allocate(PyObject* o, int dims, const int* sizes, int type, size_t* step) const
 {
  UMatData* u = new UMatData(this);
  u->data = u->origdata = (uchar*)PyArray_DATA((PyArrayObject*) o);
  npy_intp* _strides = PyArray_STRIDES((PyArrayObject*) o);
  for( int i = 0; i < dims - 1; i++ )
   step[i] = (size_t)_strides[i];
  step[dims-1] = CV_ELEM_SIZE(type);
  u->size = sizes[0]*step[0];
  u->userdata = o;
  return u;
 }
 
 UMatData* allocate(int dims0, const int* sizes, int type, void* data, size_t* step, int flags, UMatUsageFlags usageFlags) const
 {
  if( data != 0 )
  {
   CV_Error(Error::StsAssert, "The data should normally be NULL!");
   // probably this is safe to do in such extreme case
   return stdAllocator->allocate(dims0, sizes, type, data, step, flags, usageFlags);
  }
 //確保當前使用python的C API是線程安全的
  PyEnsureGIL gil;
 
  int depth = CV_MAT_DEPTH(type);
  int cn = CV_MAT_CN(type);
  const int f = (int)(sizeof(size_t)/8);
  int typenum = depth == CV_8U ? NPY_UBYTE : depth == CV_8S ? NPY_BYTE :
  depth == CV_16U ? NPY_USHORT : depth == CV_16S ? NPY_SHORT :
  depth == CV_32S ? NPY_INT : depth == CV_32F ? NPY_FLOAT :
  depth == CV_64F ? NPY_DOUBLE : f*NPY_ULONGLONG + (f^1)*NPY_UINT;
  int i, dims = dims0;
  cv::AutoBuffer<npy_intp> _sizes(dims + 1);
  for( i = 0; i < dims; i++ )
   _sizes[i] = sizes[i];
  if( cn > 1 )
   _sizes[dims++] = cn;
  PyObject* o = PyArray_SimpleNew(dims, _sizes, typenum);
  if(!o)
   CV_Error_(Error::StsError, ("The numpy array of typenum=%d, ndims=%d can not be created", typenum, dims));
  return allocate(o, dims0, sizes, type, step);
 }
 
 bool allocate(UMatData* u, int accessFlags, UMatUsageFlags usageFlags) const
 {
  return stdAllocator->allocate(u, accessFlags, usageFlags);
 }
 
 void deallocate(UMatData* u) const
 {
  if(!u)
   return;
  PyEnsureGIL gil;
  CV_Assert(u->urefcount >= 0);
  CV_Assert(u->refcount >= 0);
  if(u->refcount == 0)
  {
   PyObject* o = (PyObject*)u->userdata;
   Py_XDECREF(o);
   delete u;
  }
 }
 //基類指針,調用allocate函數(shù)進行內存分配
 const MatAllocator* stdAllocator;
};

上面是先構造好能夠相互交互的allocator。

//將PyObject的特性幅值給size,ndims,type
 int typenum = PyArray_TYPE(oarr), new_typenum = typenum;
 int type = typenum == NPY_UBYTE ? CV_8U :
    typenum == NPY_BYTE ? CV_8S :
    typenum == NPY_USHORT ? CV_16U :
    typenum == NPY_SHORT ? CV_16S :
    typenum == NPY_INT ? CV_32S :
    typenum == NPY_INT32 ? CV_32S :
    typenum == NPY_FLOAT ? CV_32F :
    typenum == NPY_DOUBLE ? CV_64F : -1;
 
 //....
 
 int ndims = PyArray_NDIM(oarr);
 //....
 
 const npy_intp* _sizes = PyArray_DIMS(oarr);
 
 const npy_intp* _strides = PyArray_STRIDES(oarr);
 for ( int i = ndims - 1; i >= 0; --i )
 {
  size[i] = (int)_sizes[i];
  if ( size[i] > 1 )
  {
   step[i] = (size_t)_strides[i];
   default_step = step[i] * size[i];
  }
  else
  {
   step[i] = default_step;
   default_step *= size[i];
  }
 }
 //....
 
//這一步直接用PyObject初始化Mat m
 m = Mat(ndims, size, type, PyArray_DATA(oarr), step);
 m.u = g_numpyAllocator.allocate(o, ndims, size, type, step);
 m.addref();

上面是將PyObject對象轉為Mat的部分代碼,具體可以參考opencv的cv2.cpp文件:..\OpenCV\sources\modules\python\src2

//將Mat轉換為PyObject*
template<>
PyObject* pyopencv_from(const Mat& m)
{
 if( !m.data )
  Py_RETURN_NONE;
 Mat temp, *p = (Mat*)&m;
 //確保數(shù)據拷貝不會對原始數(shù)據m產生破壞
 if(!p->u || p->allocator != &g_numpyAllocator)
 {
  temp.allocator = &g_numpyAllocator;
  ERRWRAP2(m.copyTo(temp));
  p = &temp;
 }
 //將Mat封裝好的userdata指針轉給Pyobject*
 PyObject* o = (PyObject*)p->u->userdata;
 //引用計數(shù)器加一
 Py_INCREF(o);
 return o;
}

3.不是所有C++的語法都能轉為python可調用的pyd文件

一個很重要的知識點是,pyd文件跟dll文件非常相似,所以生成dll比較困難的C++代碼同樣難以生成pyd,C++跟python編譯器各自編譯特性的區(qū)別也會使得轉換存在困難,比如C++的動態(tài)編譯。

下面是可以進行相互轉換的C++特性(可以用swig生成):

類;構造函數(shù)和析構函數(shù);虛函數(shù);(多重)公有繼承;

靜態(tài)函數(shù);重載(包括大多數(shù)操作符重載);引用;

模板編程(特化和成員模板);命名空間;默認參數(shù);智能指針。

下面是不能或者比較困難進行轉換的C++特性:

嵌套類;特定操作符的重載比如new和delete。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。

相關文章

  • OpenCV半小時掌握基本操作之圖像輪廓

    OpenCV半小時掌握基本操作之圖像輪廓

    這篇文章主要介紹了OpenCV基本操作之圖像輪廓,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • pytest實現(xiàn)測試用例參數(shù)化

    pytest實現(xiàn)測試用例參數(shù)化

    這篇文章主要介紹了pytest實現(xiàn)測試用例參數(shù)化,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • 利用Python將多張圖片合成視頻的實現(xiàn)

    利用Python將多張圖片合成視頻的實現(xiàn)

    這篇文章主要介紹了利用Python將多張圖片合成視頻的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-11-11
  • scrapy中如何設置應用cookies的方法(3種)

    scrapy中如何設置應用cookies的方法(3種)

    這篇文章主要介紹了scrapy中如何設置應用cookies的方法(3種),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • python自動格式化json文件的方法

    python自動格式化json文件的方法

    這篇文章主要介紹了python自動格式化json文件的方法,可實現(xiàn)將json文件格式化的功能,非常具有實用價值,需要的朋友可以參考下
    2015-03-03
  • Python Tkinter創(chuàng)建GUI應用程序的示例

    Python Tkinter創(chuàng)建GUI應用程序的示例

    Tkinter提供了豐富的功能和靈活的接口,讓開發(fā)者能夠輕松地構建出各種各樣的圖形用戶界面,本文介紹了使用Python的Tkinter庫創(chuàng)建圖形用戶界面GUI應用程序,感興趣的可以了解一下
    2024-12-12
  • 詳解Python 3.10 中的新功能和變化

    詳解Python 3.10 中的新功能和變化

    這篇文章主要介紹了詳解Python 3.10 中的新功能和變化,幫助大家更好的理解和學習使用python,感興趣的朋友可以了解下
    2021-04-04
  • Python中的隨機森林算法與實戰(zhàn)

    Python中的隨機森林算法與實戰(zhàn)

    本文詳細介紹了隨機森林算法,包括其原理、實現(xiàn)步驟、分類和回歸案例,并討論了其優(yōu)點和缺點,通過面向對象編程實現(xiàn)了一個簡單的隨機森林模型,并應用于鳶尾花分類和波士頓房價預測
    2025-01-01
  • windows下安裝python的C擴展編譯環(huán)境(解決Unable to find vcvarsall.bat)

    windows下安裝python的C擴展編譯環(huán)境(解決Unable to find vcvarsall.bat)

    這篇文章主要介紹了windows下安裝python的C擴展編譯環(huán)境(解決Unable to find vcvarsall.bat),需要的朋友可以參考下
    2018-02-02
  • 解決Python出現(xiàn)_warn_unsafe_extraction問題的方法

    解決Python出現(xiàn)_warn_unsafe_extraction問題的方法

    這篇文章主要為大家詳細介紹了解決Python出現(xiàn)'_warn_unsafe_extraction'問題的方法,感興趣的小伙伴們可以參考一下
    2016-03-03

最新評論

赤壁市| 巩义市| 正定县| 玉山县| 永善县| 沈丘县| 浦东新区| 吴江市| 清流县| 隆化县| 安塞县| 永胜县| 泰和县| 克山县| 禄劝| 黄平县| 临澧县| 天长市| 凌源市| 林周县| 界首市| 威信县| 平谷区| 八宿县| 衡水市| 泸州市| 惠安县| 马关县| 汉沽区| 蒙城县| 滦平县| 舞钢市| 德江县| 鹿泉市| 枣庄市| 玛沁县| 翁牛特旗| 汉寿县| 平利县| 朝阳县| 永春县|