python 中调用c++定义的函数

来源:互联网 发布:公司网络被限制怎么办 编辑:程序博客网 时间:2024/05/21 17:47

        最近项目需要实现这样的需求,后台更改了数据库后,需要在不重启gameserver的情况下,重新加载数据。由于前不久写过监控gameserver的监控程序,发短信那块用的python写的,就想直接在上面扩展下,添加一个非常简单的http服务器,后台改变数据后,发送一个http请求给这个监控程序,监控程序再去请求gameserver,重新加载数据。

 

        上网搜了一下,发现在python 中调用c++中函数,网上大部分方法都是将c++编成.dll(windows下)或者.so(linux下),这样和我们现在的需求不一致,c++写的程序是要一直运行,当python脚本中的httpserver接收到特定的请求再调用c++的函数。


        现在我们就不将c++定义的函数编成.dll的方法,python弄个非常简单的http server,接收到get请求后调用c++的测试函数(无参打印函数,有参的加法函数)。


其实只需要调用python提供的api直接在c++中创建python模块并将需要的函数初始化进去,在python中import此模块,调用相应的函数即可。


最主要的就是定义PyMethodDef类型的数组,例如这里使用的:

static PyMethodDef Methods[]={{"no_args_function_print", noArgsFunctionPrint, METH_NOARGS, NULL},{"args_function_add", argsFunctionAdd, METH_VARARGS, NULL},{NULL, NULL, 0, NULL} };
数组中的第一个数组变量中第一个是导出到python中使用的函数名,第二个是c++中定义的函数指针,第三个是参数类型,种类很多,我们这里只使用两种:无参用METH_NOARGS,有参用METH_VARARGS。第四个参数是此函数的doc说明。


c++中要实现的函数这样定义:static PyObject* PyMethodDef数组中定义的函数指针(PyObject *pSelf, PyObject *pParams); 里面实现逻辑,第一个参数是此函数的类类型。这里没用,第二个参数是python调用的时间传入的。


现在我们来实现上面的简单需求,先看看python脚本:python_call_c++.py

# -*- coding: UTF-8 -*-import BaseHTTPServer  import urlparse"""引入c++中定义的python模块"""import ModuleOfDefineclass WebRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):      def do_GET(self):          """         """          parsed_path = urlparse.urlparse(self.path)          message_parts = [                  'CLIENT VALUES:',                  'client_address=%s (%s)' % (self.client_address,                                              self.address_string()),                  'command=%s' % self.command,                  'path=%s' % self.path,                  'real path=%s' % parsed_path.path,                  'query=%s' % parsed_path.query,                  'request_version=%s' % self.request_version,                  '',                  'SERVER VALUES:',                  'server_version=%s' % self.server_version,                  'sys_version=%s' % self.sys_version,                  'protocol_version=%s' % self.protocol_version,                  '',                  'HEADERS RECEIVED:',                  ]          """调用c++中定义的no_args_function_print函数"""        ModuleOfDefine.no_args_function_print()        """调用c++中定义的args_function_add函数"""        return_value = ModuleOfDefine.args_function_add(1, 3)        print "python call c++ function add return value: ", return_value        for name, value in sorted(self.headers.items()):              message_parts.append('%s=%s' % (name, value.rstrip()))          message_parts.append('')          message = '\r\n'.join(message_parts)          self.send_response(200)          self.end_headers()          self.wfile.write(message)server = BaseHTTPServer.HTTPServer(('0.0.0.0',8080), WebRequestHandler)  server.serve_forever()  

这个是网上down的一个非常简单的http服务器,再看看c++代码:

#include "python.h"#include <iostream>// 测试的无参函数static PyObject* noArgsFunctionPrint(PyObject *pSelf, PyObject *pParams){std::cout << "python already call c++ funcions, this this noArgsFunctionPrint!" << std::endl;Py_INCREF(Py_None);return Py_None;}// 测试的有参函数static PyObject* argsFunctionAdd(PyObject *pSelf, PyObject *pParams){std::cout << "python already call c++ funcions, this is argsFunctionAdd" << std::endl;long x = 0;long y = 0;// 获取python调用此函数时传进的参数if (!PyArg_ParseTuple(pParams, "ii", &x, &y)){return NULL;}long result = x + y;return PyInt_FromLong(result);}// 将c++中需要导出的函数的名字、函数地址等信息保存到PyMethodDef类型的数组中// 导出到python的函数名、函数指针、函数形式(我们这使用这两种:METH_NOARGS(没参数),METH_VARARGS(有参数))、函数的doc// 最后一行的NULL时结束标记static PyMethodDef Methods[]={{"no_args_function_print", noArgsFunctionPrint, METH_NOARGS, NULL},{"args_function_add", argsFunctionAdd, METH_VARARGS, NULL},{NULL, NULL, 0, NULL} };// 调用python_call_c++.py脚本void initPython(){//初始化系统中得python解释器Py_Initialize();//python的解释器是否已经初始化,返回true(非0)表明已经初始化,返回false(0)表明没有初始化  if (!Py_IsInitialized()){std::cout << "Py_Initialize() failed" << std::endl;system("pause");return;}// 向python中添加参数名的模块if (!PyImport_AddModule("ModuleOfDefine")){std::cout << "c++ add module could not be created." << std::endl;}// 初始化添加的模块PyObject *module = Py_InitModule("ModuleOfDefine", Methods);if (!module){std::cout << "c++ add module could not be initialized." << std::endl;return;}PyRun_SimpleString("import sys");PyRun_SimpleString("sys.path.append('./')");PyObject *pName = NULL;PyObject *pModule = NULL;//载入python_call_c++.py脚本pName = PyString_FromString("python_call_c++");pModule = PyImport_Import(pName);if (!pModule){std::cout << "can not find python_call_c++.py" << std::endl;system("pause");return;}//释放资源 if (pName != NULL){Py_DECREF(pName);}if (pModule != NULL){Py_DECREF(pModule);}//关闭pythonPy_Finalize();}int main(){initPython();system("pause");return 0;}

c++ 代码中有很详细的注释了,前面也说过c++中如何调用python,可以参考下http://blog.csdn.net/u014489596/article/details/42146233
可以测试下,开启c++程序后,打开浏览器,输入http://localhost:8080/就行了。


0 0
原创粉丝点击