python被c调用
1. python C API浣跨敤镞堕渶瑕佹敞镒忎粈涔
涓锛氱敤C API涓篜ython鍐机璇瑷鍑芥暟锛屼互鏂逛究Python涓璋幂敤
1. 棣栧厛瀹炵幇涓涓鐗瑰畾铡熷瀷镄勫嚱鏁帮纴鐢≒ython C API𨱒ュ疄鐜扮殑璇濓纴镓链夊嚱鏁板繀椤绘槸杩欑嶅师鍨嬨傚繀椤绘槸绫讳技杩欐牱镄
PyObject *Fun(PyObject *self, PyObject *args)
self搴旇ユ槸鍦ㄧ敤绫荤殑镞跺欐墠浼氱敤鍒帮纸鎴戞病链夌敤鍒帮级锛宎rgs灏辨槸鍑芥暟镄勫弬鏁般傚洜涓篴rgs鏄涓涓狿yObject*绫诲瀷锛埚彲浠ヤ唬琛≒ython璇瑷涓镄勪换浣旷被鍨嬶级
2. 灏嗗弬鏁拌浆鎹㈡垚C 璇瑷琛ㄧず镄勫唴瀹癸纴鐢≒yArg_ParseTuple鍑芥暟銆
3. 镓ц屽畬闇瑕佺殑镎崭綔钖庯纴涔熷繀椤昏繑锲炰竴涓狿yObject*绫诲瀷镄勫笺傞氲繃Py_BuildValue鍑芥暟𨱒ユ瀯寤恒
杩欓噷瑕佽寸殑鏄锛屽亣濡傚笇链涜繑锲炰竴涓猅uple绫诲瀷镄勫硷纴鍙浠ュ厛鐢
PyObject *tuple = Py_BuildValue("(iis)", 1, 2, "three");
褰㈠纺𨱒ユ瀯寤猴纴锅囧傚緢澶氱殑璇濓纴鍙浠ョ敤涓嬮溃镄勬柟寮忔潵鏋勫缓
PyObject *t;
t = PyTuple_New(3);
PyTuple_SetItem(t, 0, PyLong_FromLong(1L));
PyTuple_SetItem(t, 1, PyLong_FromLong(2L));
PyTuple_SetItem(t, 2, PyString_FromString("three"));
杩欎竴镣瑰湪鍒氩紑濮嫔紑宸ョ殑镞跺栾糠𨱍戜简寰堜箙銆
4. 灏呜佽緭鍑虹殑镓链夊嚱鏁版斁鍏ヤ竴涓鏁扮粍涓锛屾暟缁勭殑缁撴瀯鏄锛
struct PyMethodDef {
const char *ml_name; /* The name of the built-in function/method */
PyCFunction ml_meth; /* The C function that implements it */
int ml_flags; /* Combination of METH_xxx flags, which mostly
describe the args expected by the C func */
const char *ml_doc; /* The __doc__ attribute, or NULL */
};
鏁扮粍浠{NULL, NULL}缁撴潫
5. 鏋勯犱竴涓狿ython import镞跺埯濮嫔寲镄勫嚱鏁
绫讳技
PyMODINIT_FUNC
initexample(void)
{
Py_InitMole("example", example_methods);
}
杩欓噷链変釜鐗瑰埆闇瑕佹敞镒忕殑鏄锛屽埯濮嫔寲鍑芥暟钖嶅瓧链変弗镙艰佹眰锛宨nit钖庨溃蹇呴’璺熸ā鍧楀悕锛屽惁鍒橮ython镓句笉鍒扮‘瀹氱殑鍑芥暟浼氭姤娌℃湁鍒濆嫔寲鍑芥暟镄勯敊璇
镓╁𪾢妯″潡鍐椤畬钖庯纴缂栬疟鎴愬姩镐佸簱锛圥ython瑕佹眰姝ゅ姩镐佸簱钖嶅瓧涓簆yd,瀹为檯灏辨槸鏀逛釜钖庣紑钥屽凡锛夈傚氨鍙浠ョ洿鎺ュ湪Python鑴氭湰涓鐢╥mport镄勬柟寮忓姞杞戒简锛屽逛簬浣跨敤𨱒ヨ达纴镙规湰涓嶉渶瑕佺煡阆撴ゅ簱鏄鐢– API镓╁𪾢鍐欑殑杩樻槸鐩存帴鐢≒ython璇鍙ュ啓镄勶纸杩欑偣Lua锅氱殑涔熸槸涓镙峰ソ锛
链钖庯纴python镄勬簮浠g爜涓闄勫甫浜嗕竴涓鍙锅欤xample_nt镄勪緥瀛愶纴鍙浠ュ弬钥冧竴镙凤纴瀹屾暣镄勬墿灞曚唬镰佸备笅锛
#include "Python.h"
static PyObject *
ex_foo(PyObject *self, PyObject *args)
{
printf("Hello, world/n");
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef example_methods[] = {
{"foo", ex_foo, METH_VARARGS, "foo() doc string"},
{NULL, NULL}
};
PyMODINIT_FUNC
initexample(void)
{
Py_InitMole("example", example_methods);
}
浜岋紟C璇瑷涓璋幂敤Python璇鍙
棣栧厛锛寁oid Py_Initialize()鐢ㄦ潵鍒濆嫔寲锛寁oid Py_Finalize()鐢ㄦ潵缁撴潫Python镄勮皟鐢锛岃繖鏄蹇呴’瑕佺殑銆
鐕幂伀鍒嗕袱绉嶆儏鍐碉纴锅囧备粎浠呮槸鍑犳浔璇鍙ョ殑璇濓纴闾d箞浠PyRun_涓哄墠缂镄勪竴浜涘嚱鏁伴兘寰埚ソ鐢锛屾瘆濡
int PyRun_SimpleString(const char *command)
鍑芥暟灏卞彲浠ョ洿鎺ユ墽琛屼竴𨱒char*镄凯ython璇鍙ャ
闇瑕佽幏寰楄繑锲炲煎缑璇
PyObject* PyRun_String(const char *str, int start, PyObject *globals, PyObject *locals)
涔熷緢濂界敤锛屼互涓娄袱涓鍑芥暟鐢ㄦ潵澶勭悊Python婧愪唬镰佸凡缁忚诲叆鍐呭瓨镄勬儏鍐碉纴鍦ㄦ枃浠朵腑镄勬椂鍊
int PyRun_SimpleFile(FILE *fp, const char *filename)
PyObject* PyRun_File(FILE *fp, const char *filename, int start, PyObject *globals, PyObject *locals)
浣跨敤绫讳技銆备笉澶氲蹭简銆
锅囧傛槸涓妯″潡镄勮瘽锛堟瘆濡备竴涓鍑芥暟锛夛纴甯屾湜鍦–璇瑷涓璋幂敤镄勮瘽闾d箞浣跨敤璧锋潵灏辩◢寰澶嶆潅浜嗕竴镣广傝繖绉嶆儏鍐电殑闇瑕佸湪浜庝綘鍙浠ヤ粠C璇瑷涓钖慞ython鍑芥暟涓浼犲叆鍙傛暟骞朵笖镓ц岋纴铹跺悗銮峰彇缁撴灉銆
姝ゅ勫张鍒嗕负鍑犵嶆儏鍐碉细
鍦ㄦ枃浠朵腑锛屽湪鍐呭瓨涓锛岀紪璇戣繃镄勶纴婧愪唬镰併
鍦ㄦ枃浠朵腑閮藉緢濂借В鍐筹纴鍜屼笂闱涓镙枫傝繖閲屼富瑕佽插湪鍐呭瓨涓镄勬儏鍐点傦纸浜嫔疄涓婃垜宸ヤ綔涓闇瑕佸苟涓旇楄垂浜嗗緢闀挎椂闂存墠镓惧埌瑙e喅鏂规硶镄勫氨鏄杩欑嶆儏鍐碉级
链缂栬疟镞讹细锛堜篃灏辨槸婧愪唬镰侊级
1.阃氲繃
PyObject* Py_CompileString(const char *str, const char *filename, int start)
API棣栧厛缂栬疟涓娆°傛API镄勫弬鏁版垜璇存槑涓涓嬶纴str灏辨槸鍐呭瓨涓镄勬簮浠g爜锛宖ilename涓昏佹槸鍑洪敊镞舵姤阌栾鐢ㄧ殑锛屼簨瀹炴祴璇曡瘉鏄庯纴浣犻殢镒忕粰涓瀛楃︿覆涔熸病链夊叧绯伙纴浣嗙粰NULL鍙傛暟鍦ㄨ繍琛屾椂蹇呯劧鎶ラ敊銆俿tart鎴戜竴鑸鐢ㄧ殑鏄疨y_file_input锛屽洜涓虹殑纭鏄浠庢枃浠朵腑璇诲彇杩囨潵镄勶纴鐩稿圭殑杩樻湁Py_single_input鐢ㄦ潵琛ㄧず涓𨱒¤鍙ワ纴Py_eval_input镄勭敤娉曟垜涔熶笉鏄澶娓呮氥
婧愪唬镰侀氲繃姝ゅ嚱鏁拌皟鐢ㄥ悗锛岃幏寰楃紪璇戝悗镄凯yObject*,锛埚叾瀹炲亣濡傝窡杩涙簮浠g爜涓铡荤湅锛屾槸涓涓狿yCodeObject缁撴瀯锛夊亣璁惧懡钖崭负lpCode銆
2.姝ゆ椂鍐嶈皟鐢ˋPI
PyObject* PyImport_ExecCodeMole(char *name, PyObject *co)
瀵煎叆妯″潡銆傚弬鏁颁篃璇存槑涓涓嬶纴name涓哄煎叆镄勬ā鍧楀悕锛宑o灏辨槸鍓嶉溃缂栬疟杩囩殑浠g爜瀵硅薄锛坙pCode锛夈傝繑锲炵殑灏辨槸妯″潡瀵硅薄浜嗭纴锅囱惧懡钖崭负lpMod銆
3.鍐嶈皟鐢ˋPI
PyObject* PyObject_GetAttrString(PyObject *o, const char *attr_name)
銮峰缑鍑芥暟瀵硅薄銆俹灏辨槸妯″潡瀵硅薄锛坙pMod锛,attr_name灏辨槸浣犳兂瑕佽皟鐢ㄧ殑鍑芥暟钖崭简锛屽亣璁惧彨main镄勫嚱鏁帮纴灏辨槸钬漨ain钬濓纴铹跺悗杩斿洖镄勫氨鏄鍑芥暟瀵硅薄锛屽亣璁惧懡钖崭负lpFun銆
4.姝ゆ椂鍙浠ョ敤API
int PyCallable_Check(PyObject *o)
铡绘镆ヤ竴涓嬫槸涓嶆槸銮峰缑浜嗕竴涓鍑芥暟銆傚亣濡傜‘瀹氱殑璇濓纴灏卞彲浠ョ洿鎺ョ敤
PyObject_Call寮澶寸殑涓镞忓嚱鏁拌皟鐢╨pFun浜嗐傝繖浜涘嚱鏁板寘𨰾寰埚氾纴涓鑸灏辨槸杈揿叆鍙傛暟镄勪笉钖岋纴浣嗘槸鏁堟灉閮芥槸涓镙风殑锛屽氨鏄璋幂敤鍑芥暟钥屽凡銆傚弬鏁颁竴鑸鍙浠ラ氲繃鍓嶉溃璇磋繃镄刡uild鍑芥暟𨱒ヨ幏寰楋纴杩斿洖鍊间篃鏄銮峰缑涓涓狿yObject*,鍙浠ラ氲繃PyArg_闾d釜鍑芥暟𨱒ヨ幏鍙栵纴浣嗘槸濂藉儚涓嶅お濂斤纴闾f槸鍒嗘瀽鍙傛暟鐢ㄧ殑銆傛帹钻愮敤纭瀹氱被鍨嬶纸锅囱句负type锛夌殑绫讳技Py[type]_As镄勫嚱鏁版潵銮峰彇銆
姣斿傦细
long PyLong_AsLong(PyObject *pylong)銮峰彇long
double PyLong_AsDouble(PyObject *pylong)銮峰彇double
杩欓噷𨱍宠寸殑鏄锛屽簲璇ユ湁鐩存帴浠庢簮浠g爜涓銮峰彇鍑芥暟璋幂敤瀵硅薄镄勬柟寮忥纴浣嗘槸鎴戞湰浜烘病链夎瘯鍑烘潵锛屾湁浜虹煡阆撹蜂竴瀹氲祼鏁欙紒
缂栬疟杩囩殑浠g爜锛
瀵逛簬缂栬疟杩囩殑浠g爜鍜屼笂闱㈠氨鏄銮峰缑缂栬疟钖庣殑PyCodeObject瀵硅薄,褰撶劧鍦ㄦ簮浠g爜涓琛ㄧず杩樻槸PyObject*镄勬柟娉曚笉钖岋纸涓娄緥涓镄刲pCode锛夈
褰撶劧瑕佹兂浠ュ悗銮峰缑涓涓缂栬疟钖庣殑lpCode,镊铹惰佸厛缂栬疟涓涓嫔暒銆备絾鏄绾绮圭紪璇戞垚pyc缁揿熬镄勬枃浠跺悗锛岀洿鎺ヨ诲叆鍐呭瓨锛屾垜娌℃湁镓惧埌灏嗗叾杞鍖栦负PyCodeObject瀵硅薄镄勬柟娉曪纸涔熷笇链涙湁浜虹煡阆撹兘锻婅瘔鎴戯紒锛
鎴戞垒鍒扮殑鏂规硶鏄鍏堢敤
PyObject* PyMarshal_WriteObjectToString(PyObject *value, int version)
void PyMarshal_WriteLongToFile(long value, FILE *file, int version)
涓や釜鍑芥暟鍏堟妸PyCodeObject瀵硅薄(lpCode)搴忓垪鍖栧埌鏂囦欢鎴栬呭唴瀛树腑銆
鍐嶅湪闇瑕佺殑镞跺欑敤鍑芥暟
PyObject* PyMarshal_ReadObjectFromFile(FILE *file)
PyObject* PyMarshal_ReadObjectFromString(char *string, Py_ssize_t len)
璇诲嚭𨱒ワ纴璇诲嚭𨱒ョ殑PyObject*鍏跺疄灏辨槸𨱍宠佺殑PyCodeObject瀵硅薄浜(lpCode)銆傛帴涓嬫潵镄勬ラや笌链缂栬疟镞剁殑姝ラや竴镙枫
鍏夋槸杩欎釜镓镟茬殑鏂规硶鎴戣缮鏄鍙傝冭佹荤粰镄勫崐杈硅祫鏂椤弽澶岖爷绌跺嚭𨱒ョ殑銆傝岀湡姝g洿鎺ユ湁鏁堢殑鏂规硶鎴戣缮鏄娌℃湁镓惧埌銆
2. 【python-C相互调用】python里的dict如何作为参数传入.so中的c语言函数
#include<stdio.h>
#include<stdlib.h>
#include<Python.h>
staticPyObject*
wmf_reverse(PyObject*self,PyObject*args,PyObject*kwargs){
staticchar*kwlist[]={"name",NULL};
char*name=NULL;
PyObject*retval=NULL;
//问题1:只取一个字符串,format应该是"s"
//>>>if(PyArg_ParseTupleAndKeywords(args,keyds,"isi",kwlist,&name))
if(PyArg_ParseTupleAndKeywords(args,kwargs,"s",kwlist,&name)){
retval=(PyObject*)Py_BuildValue("i",1);
printf("%s ",name);
//问题2:不要释放
//>>>free(name);
}else{
retval=(PyObject*)Py_BuildValue("i",0);
}
returnretval;
}
staticPyMethodDef
wmf_methods[]={
{"reverse",(PyCFunction)wmf_reverse,METH_VARARGS|METH_KEYWORDS,"reverse"},
//问题3:方法定义表,应该用一条空记录来表示结束。
{NULL,NULL,0,NULL},
};
//问题4:没有定义mole
staticstructPyMoleDef
wmf_mole={
PyMoleDef_HEAD_INIT,
"wmf",/*nameofmole*/
NULL,/*moledocumentation,maybeNULL*/
-1,/*sizeofper-interpreterstateofthemole,
or-.*/
wmf_methods,
};
//问题5:入口函数要声明为:PyMODINIT_FUNC
PyMODINIT_FUNC
PyInit_wmf(void){
//问题6:Py_InitMole要初始化的是模块,不是方法。所以传方法定义是错误的。
//另外,python2.x是用Py_Init_mole,python3.x改用PyMole_Create了。
//两者略有差别,自己注意一下吧。这里我用的是python3.x。
//Py_InitMole("wmf",ExtestMethods);
PyObject*m;
m=PyMole_Create(&wmf_mole);
if(m==NULL){
returnNULL;
}
returnm;
}
3. C/C++ 调用Python
在项目开发中,有时需要将Python脚本与C/C++程序进行整合,实现复杂功能或高效执行任务。以下是C/C++调用Python的详细步骤及原理概述。
首先,了解Python与C/C++的交互方式。Python提供了一系列的C/C++接口,允许C/C++程序直接调用Python代码或访问Python对象。关键在于使用Python的头文件`Python.h`,以及通过调用`python-config`脚本获取编译和链接参数。
为了验证链路是否畅通,可编写一个简单的C++示例程序,通过`PyRun_SimpleString`函数执行Python代码。该函数提供了直接执行Python代码的高级接口,但在处理复杂数据类型或与C/C++交换数据时,需要借助更底层的接口。
初始化Python解释器是调用Python代码的首要步骤。通常在系统初始化时调用`Py_Initialize`,并在程序结束时调用`Py_Finalize`以确保资源的正确释放。在多线程环境中,注意GIL(全局解释器锁)的影响,它限制了线程在解释器中同时运行的能力,可能导致性能瓶颈。解决方法通常是通过多进程或C代码实现多线程。
一切皆对象是Python的核心概念,意味着在程序执行过程中,所有的变量、函数、类等都被表示为对象。在Python/C API中,`PyObject*`类型指针用于操作这些对象。通过这一机制,可以实现C/C++与Python对象的交互,包括获取Python代码中的对象、将C/C++变量转换为Python对象,以及调用Python函数等。
在C/C++中获取Python对象时,可以利用Python的构造函数将C/C++变量转换为Python对象。这些对象在堆中创建,并由Python解释器管理,通过引用计数确保内存的正确释放。引用计数机制与垃圾回收共同管理对象的生命周期,确保内存的高效利用。
对于函数调用,Python/C API提供了一系列的函数,如`PyObject_Call`系列,允许C/C++程序调用Python函数或方法。参数传递可以是Python对象的直接引用或通过格式化字符串和变量组合而成的元组。
了解Python/C API的引用计数机制是确保程序正确性的重要部分。Python使用引用计数与垃圾回收管理内存,当对象的引用计数为零时,该对象将被释放。正确地管理引用计数避免内存泄漏,同时要谨慎处理所有权和借用概念,以确保程序的健壮性和安全性。
通过以上步骤,C/C++程序能够与Python代码无缝集成,实现高效的数据处理和复杂逻辑,满足项目开发的多样需求。
4. 怎样把Python代码嵌入到C程序
步骤1:安装Python开发包
由于需要访问Python/C API,首先安装Python开发包。
在Debian,Ubuntu或Linux Mint中:
在CentOS,Fedora或RHEL中:
安装成功后,Python头文件在/usr/include/python2.7。根据Linux发行版的不同,确切的路径可能是不相同的。例如,CentOS 6中是/usr/include/python2.6。
步骤2:初始化解释器并设置路径
C中嵌入Python的第一步是初始化Python解释器,这可以用以下C函数完成。
初始化解释器后,需要设置你的C程序中要导入的Python模块的路径。例如,比如你的Python模块位于/usr/local/moles。然后使用以下C函数调用来设置路径。
步骤3:数据转换
C中嵌入Python最重要的方面之一是数据转换。从C中传递数据到Python函数,需要首先将数据从C数据类型转换到Python数据类型。Python/C API提供各种函数来实现这。例如,转换C字符串到Python字符串,使用PyString_FromString函数。
另外一个类似函数PyInt_FromLong,将C中long数据类型转换为Python int。每个Python/C API函数返回一个PyObject类型的引用。
步骤4:定义一个Python模块
当你想嵌入Python代码到另一种语言如C,该代码需要被写成Python模块,然后用另一种语言“导入”。所以让我们来看看如何在C中导入Python模块。
为了进行说明,我们实现一个简单的Python模块例子如下:
以上的Python函数有一个字符串作为参数并返回两个重复的字符串。例如,如果输入字符串是“cyberpersons”,该函数返回'cyberpersonscyberpersons'。此模块文件命名为“printData.py”并将它放在前面声明的Python模块目录中(/usr/local/moles)。
步骤5:加载一个Python模块
现在你已经定义了Python模块,是时候在C程序中加载它了。导入模块的C代码看起来像这样:
步骤6:构建函数的参数
当加载一个模块时,可以调用模块中定义的Python函数。通常,我们需要传递一个或多个参数到一个Python函数。我们必须构建一个Python元组对象,它包括Python函数中的参数。
在我们的例子中,printData函数定义带一个参数的模块。因此,我们构建一个大小是一的Python元组对象如下。我们可以使用PyTuple_SetItem设置元组对象的每个项。
我们已经成功构建一个参数传递到函数调用,是时候从C程序调用python函数了。
步骤7:调用Python函数
一旦成功创建Python元组对象作为函数参数,我们可以调用一个带参数的Python函数。为此,通过使用PyObject_GetAttrString首先获得模块中定义的函数的引用,然后使用PyObject_CallObject调用该函数。例如:
步骤8:错误检查
避免运行时错误的常见方法是检查函数的返回值并根据返回值采取适当的行动。类似于C程序中的全局变量errno,Python/C API提供一个全局指示符,它报告最后发生的错误。当Python/C API函数失败,全局指示符设置为指示错误,并且PyErr_Print可以用于显示相应的人类可读的trackback。例如:
在你的应用程序中,你可以轻松地将各种错误检查。
这里是完整的C程序,它如本教程描述的嵌入Python代码。
步骤9:编译和执行
保存以上代码到finalCode.c,并且链接Python库(-lpython2.7)编译该代码。根据发行版的不同,可能使用不同的版本(例如,-lpython2.6)。