<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
將Python安裝目錄下的include
和libs
資料夾引入到專案中,將libs目錄下的python37.lib複製一份為python37_d.lib
def Hello(): print("Hello") def Add(a,b): return a+b
#include <Python.h> using namespace std; int main() { Py_Initialize(); //初始化,建立一個Python虛擬環境 if (Py_IsInitialized()) { PyObject* pModule = NULL; PyObject* pFunc = NULL; pModule = PyImport_ImportModule("test_python"); //引數為Python指令碼的檔名 if (pModule) { pFunc = PyObject_GetAttrString(pModule, "Hello"); //獲取函數 PyEval_CallObject(pFunc, NULL); //執行函數 } else { printf("匯入Python模組失敗...n"); } } else { printf("Python環境初始化失敗...n"); } Py_Finalize(); }
Python3.6提供給C/C++介面函數,基本都是定義pylifecycle.h
,pythonrun.h
,ceval.h
中。
#include<Python.h> //新增python的宣告 using namespace std; int main() { Py_Initialize(); //1、初始化python介面 //初始化使用的變數 PyObject* pModule = NULL; PyObject* pFunc = NULL; PyObject* pName = NULL; //2、初始化python系統檔案路徑,保證可以存取到 .py檔案 PyRun_SimpleString("import sys"); PyRun_SimpleString("sys.path.append('./')"); //3、呼叫python檔名。當前的測試python檔名是test.py。在使用這個函數的時候,只需要寫檔案的名稱就可以了。不用寫字尾。 pModule = PyImport_ImportModule("test"); //4、呼叫函數 pFunc = PyObject_GetAttrString(pModule, "AdditionFc"); //5、給python傳引數 PyObject* pArgs = PyTuple_New(2);//函數呼叫的引數傳遞均是以元組的形式打包的,2表示引數個數。如果AdditionFc中只有一個引數時,寫1就可以了。這裡只先介紹函數必須有引數存在的情況。 PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 2)); //0:表示序號。第一個引數。 PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 4)); //1:也表示序號。第二個引數。i:表示傳入的引數型別是int型別。 //6、使用C++的python介面呼叫該函數 PyObject* pReturn = PyEval_CallObject(pFunc, pArgs); //7、接收python計算好的返回值 int nResult; PyArg_Parse(pReturn, "i", &nResult);//i表示轉換成int型變數。在這裡,最需要注意的是:PyArg_Parse的最後一個引數,必須加上「&」符號。 //8、結束python介面初始化 Py_Finalize(); }
python呼叫c++一種是基於extern 的方式,另一種是swig
初級版:
首先先看一下Python呼叫c
C程式碼:
#include <stdio.h> #include <stdlib.h> int foo(int a, int b) { printf("you input %d and %dn", a, b); return a+b; }
Python程式碼:
import ctypes lib = ctypes.CDLL("./libpycall_c.so") lib.foo(1, 3) print '***finish***'
編譯:
gcc -g -o libpycall_c.so -shared -fPIC pycall_c.c
然後基於c++改造上述程式碼(使用g++編譯生成C動態庫的程式碼中的函數或者方法,需要使用extern “C”來進行編譯)
c++程式碼:
#include <iostream> using namespace std; int foo(int a, int b){ cout << "the number you input:" << a << "t" << b << endl; return a + b; } extern "C" { int foo_(int a, int b){ foo(a, b); } }
python程式碼:
import ctypes lib = ctypes.CDLL("./libpycall.so") lib.foo_(1, 3) print '***finish***'
編譯:
g++ -g -o libpycall.so -shared -fPIC pycall.cpp
升級版:
c++定義一個類,通過python呼叫c++類的方法
#include <iostream> using namespace std; class TestLib{ private: int number = 0; public: void set_number(int num){ number = num; } int get_number(){ return number; } }; extern "C" { TestLib obj; int get_number(){ return obj.get_number(); } void set_number(int num){ obj.set_number(num); } }
python 程式碼:
import ctypes lib = ctypes.CDLL("./libpycall.so") print lib.get_number() #0 lib.set_number(10) print lib.get_number() #10
編譯:
g++ -g -o libpycall.so -shared -fPIC -std=c++11 pycall.cpp
Swig
是一種軟體開發工具,能讓一些指令碼語言呼叫C/C++語言的介面。它實現的方法是,通過編譯程式將C/C++的宣告檔案(.i檔案)編譯成C/C++的包裝器原始碼(.c或.cxx)。通過直接呼叫這樣的包裝器介面,指令碼語言可以間接呼叫C/C++語言的程式介面。
參考地址:https://github.com/swig/swig
首先安裝,原始碼或者pip
案例:
有這樣一段C的程式碼,檔名為example.c
/* File : example.c */ double My_variable = 3.0; /* Compute factorial of n */ int fact(int n) { if (n <= 1) return 1; else return n*fact(n-1); } /* Compute n mod m */ int my_mod(int n, int m) { return(n % m); }
你想在你的指令碼語言的程式碼裡面呼叫fact函數。你可以通過一段非常簡單的SWIG指令碼,檔名為example.i:(這裡的格式非常重要,即使第一行的註釋也不能省略)
/* File : example.i */ %module example %{ /* Put headers and other declarations here */ extern double My_variable; extern int fact(int); extern int my_mod(int n, int m); %} extern double My_variable; extern int fact(int); extern int my_mod(int n, int m);
這段.i檔案分成3個部分:
%module example
,%module
是SWIG指令碼的一個命令,它表示生成的包裝器將在一個模組內的名稱。xxxx_wrap.c
或xxxx_wrap.cxx
檔案中。接下來以linux作業系統下,為python語言生成介面為例:
swig -python example.i
執行上述語句會生成兩個檔案example.py
和example_wrap.c
。example.py
就是python語言可以呼叫的example模組,而example_wrap.c則封裝了example.c
的封裝器。
然後執行第二步:
gcc -c -fPIC example.c example_wrap.c -I/usr/include/python2.7
執行該步會生成兩個o檔案,example.o
和example_wrap.o
。
最後執行:
g++ -shared example.o example_wrap.o -o _example.so
這一步會將上面兩個o檔案封裝成一個新的動態庫,_example.so
。在這之後就可以在python內直接呼叫example.c提供的介面了。
import example print example.fact(3) print example.cvar.My_variable #注意這裡的引數不能直接用,得用cvar
到此這篇關於python 與c++相互呼叫實現的文章就介紹到這了,更多相關python 與c++相互呼叫內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45