Python读取Postgresql后将数据传递给C++共享库
2015-07-22 10:21
731 查看
Python调用C++,参数传递的方式有很多种,单个参数传递可以参考一下链接
http://blog.csdn.net/fxjtoday/article/details/6059874
下面介绍一下如何使用Python读取Postgresql数据库数据,并传递给调用的C++函数,其实就是扩展一下上面给出的链接的第二种方法。Boost.python库没使用过,不过看上去貌似更加的简单方便,毕竟是再一次的封装,根据一般经验,越往上层封装,编码细节的要求就越低,这样可以把精力放在程序的逻辑架构和业务处理上。所以如果想用好Python
+ C++编程,学习使用Boost库会使得开发更加得心应手。
直接上代码,分析代码:
下面是C++代码中用到的自定义数据结构:
下面是要编成共享库的C++源码:
将上述代码编译成共享库:g++ -o -DoubleMerge.so DoubleMerge.cpp -fpic -shared
下面贴上Python的代码
Python调用C++,参数传递的方式有很多种,单个参数传递可以参考一下链接
http://blog.csdn.net/fxjtoday/article/details/6059874
下面介绍一下如何使用Python读取Postgresql数据库数据,并传递给调用的C++函数,其实就是扩展一下上面给出的链接的第二种方法。Boost.python库没使用过,不过看上去貌似更加的简单方便,毕竟是再一次的封装,根据一般经验,越往上层封装,编码细节的要求就越低,这样可以把精力放在程序的逻辑架构和业务处理上。所以如果想用好Python
+ C++编程,学习使用Boost库会使得开发更加得心应手。
直接上代码,分析代码:
下面是C++代码中用到的自定义数据结构:
typedef struct { double x; double y; } GEO_POINT; typedef struct { int link_id; int tilex; int tiley; string road_name; vector<GEO_POINT> vstShplist; } RoadRec;
下面是要编成共享库的C++源码:
//DoubleMerge.cpp
#include <python2.7/Python.h> //定义Python调用的接口函数 PyObject* DoubleMerge(PyObject* self,//这个参数 PyObject* args)//Python代码传进来的参数,是一个python类型,列表或者字典或者元组等 { PyObject* datalist = NULL; PyArg_ParseTuple( args,"O",&datalist );//先从参数列表中解析出来python参数对象 vector<RoadRec> roadlist;//自定义类型 int tilex = 0; int tiley = 0; for ( int i = 0; i < PyList_Size(datalist); ++i ) { //这里python传进来的是数据库表中的数据,是个列表,列表里面的元素都是元组,下面的python代码会看到 //从列表中获取下标为i的元组 PyObject* onerec = PyList_GetItem( datalist,i ); RoadRec road; //解析元组中的每一个数据 int link_id = PyInt_AsLong( PyTuple_GetItem( onerec,0 ) ); tilex = PyInt_AsLong( PyTuple_GetItem( onerec,1 ) ); tiley = PyInt_AsLong( PyTuple_GetItem( onerec,2 ) ); //cout<<"Link_id:"<<link_id<<"x:"<<tilex<<"y:"<<tiley<<endl; string road_name = (string)PyString_AsString( PyTuple_GetItem( onerec,3 ) ); string str_geom = (string)PyString_AsString( PyTuple_GetItem( onerec,4 ) ); road.link_id = link_id; road.road_name = road_name; //这里ParseGeoPoint函数的作用是将'LINESTRING(0 0,1 1)'这样的字符串中的点解析出来放在一个vector<GEO_POINT>结构中 if ( FAILURE == ParseGeoPoint( str_geom,road.vstShplist ) ) { return NULL; } roadlist.push_back( road ); } PyObject* resultdata = PyList_New(0); vector<RoadRec> result; //上面我们已经将Python传进来的数据表数据转成了C++类型,下面这个函数就是对数据进行处理, //这里涉及到业务代码,因此不进行扩展 MergeLines(roadlist,result); //结果出来以后,下面差不多就是上面代码的一个逆过程 int cnt = result.size(); for (int i = 0; i < cnt; ++i) { //创建一个元组,其实就是数据表中的一条记录 PyObject* pTuple = PyTuple_New(5); RoadRec& link = result.at(i); string str_geo; //将vector<GEO_POINT>这样的结构打包成'LINESTRING(0 0,1 1)'这样的字符串 PacketGeoPoint( link.vstShplist,str_geo ); //设置元组(一条数据表记录)中的所有字段的值 PyTuple_SetItem( pTuple,0,Py_BuildValue( "i",link.link_id ) ); PyTuple_SetItem( pTuple,1,Py_BuildValue( "i",tilex ) ); PyTuple_SetItem( pTuple,2,Py_BuildValue( "i",tiley ) ); PyTuple_SetItem( pTuple,3,Py_BuildValue( "s",link.road_name.c_str() ) );//不能传入string类型,应该传入char*类型 PyTuple_SetItem( pTuple,4,Py_BuildValue( "s",str_geo.c_str() ) ); //所有的记录都添加到列表中,这个列表就代表数据库一张表的数据 PyList_Append( resultdata,pTuple ); } //返回列表,其实就是返回的一张数据表 return resultdata; } //这个函数现在还没有弄太清楚,就是知道函数的名字就是上面那个函数DoubleMerge前面加上init //如果你的Python代码表调用的函数是DoubleMerge,这个函数名就必须定义为initDoubleMerge, //应该是在python导入C++库的时候"通知"DoubleMerge是可以调用的函数吧,原理不太清楚 //METH_VARARGS是参数传递的标准形式,它通过Python的元组在Python解释器和C函数之间传递参数,所以上面有这么一个操作 //PyArg_ParseTuple( args,"O",&datalist ); //若采用METH_KEYWORD方式,则Python解释器和C函数之间将通过Python的字典类型在两者之间进行参数传递 //关于下面这个函数的详细说明,可以参考一下链接 //http://www.ibm.com/developerworks/cn/linux/l-pythc/ PyMODINIT_FUNC initDoubleMerge(void) { static PyMethodDef methods[] = { {"DoubleMerge", (PyCFunction)DoubleMerge, METH_VARARGS, "merge double lines"}, {NULL, NULL, 0, NULL} }; Py_InitModule("DoubleMerge", methods); }
将上述代码编译成共享库:g++ -o -DoubleMerge.so DoubleMerge.cpp -fpic -shared
下面贴上Python的代码
import psycopg2 import psycopg2.extras import DoubleMerge #导入编译好的C++库 #设置一下链接数据库的相关信息 DATABASE_HOST = "127.0.0.1" DATABASE_PORT = 5432 DATABASE_NAME = "test" DATABASE_USERNAME = "postgres" DATABASE_PASSWORD = "postgres" if __name__ == "__main__": #链接数据库 conn = psycopg2.connect(database=DATABASE_NAME, user="postgres", password="postgres", host=DATABASE_HOST, port="5432") cur = conn.cursor() sql = "select gid,tilex,tiley,road_name,st_astext(st_transform(the_geom,900913))\ from roadlist where road_name is not null" #执行SQL语句 cur.execute(sql) #获取所有记录 rows = cur.fetchall() #如果print一下rows,我们会发现,打印的结果是: #[(字段1,字段2,字段3),(字段1,字段2,字段3),(字段1,字段2,字段3),(字段1,字段2,字段3)] #可以看出,数据库表中的一条记录,读到python中就是一个元组,所有字段又放在一个列表中 #因为本实例读取的是空间道路数据,空间数据的组织形式是按tile组织, #因此我们根据tilex和tiley,算出tileid,并把列表数据按照不同的tileid组织成字典 sourcedata = {} for i in rows: tileid = i[1] << 8 | i[2] if tileid in sourcedata: sourcedata[tileid].append(i) else: sourcedata[tileid] = [i] #print sourcedata print "Create newtable table..." #创建我们要写入的新表 sql = "drop table if exists newtable;\ create table newtable(link_id integer,tilex integer,tiley integer ,road_name character varying);\ select addgeometrycolumn('newtable','the_geom',900913,'LINESTRING',2);commit;" cur.execute( sql ) #result存放的是一个tile的所有记录 result = [] #循环处理所有tile for tileid in sourcedata: print "Tile ID:" ,tileid result = DoubleMerge.DoubleMerge( sourcedata[tileid] ) #此处调用的就是我们编译好的C++库函数 #将结果一条一条插入数据库中 for re in result: link_id,tilex,tiley,roadname,strgeo = re values = str(link_id) + "," + str(tile_8_x) + "," + str(tile_8_y) + "," values = values + "$$" + roadname + "$$,st_geomfromtext('LINESTRING(" + strgeo + ")',900913)" sql = "insert into newtable(link_id,tilex,tiley,road_name,the_geom) values("+values+");" cur.execute( sql ) conn.close()这样就完成了在Python中读取Postgresql数据库中的数据,并将数据传递给C++代码,处理以后再写入到Postgresql数据库中,都说python是个很好的语言,因为刚接触不久,不敢妄作评论,不过python开发确实可以忽略很多C/C++开发的细节,还可以很方便的嵌入C/C++,java等常用语言,这样就可以取各种语言之所长,不仅开发效率高,代码执行效率也不低,不过这样开发带来一个问题,就是调试,不能像VS,VC,Eclipse单调一种语言这么的方便,或许有很好的调试技巧,只是我还没有用到。
相关文章推荐
- C语言之单链表的插入、删除与查找
- C++继承与多态问题
- 黑马程序员_C语言基础_数组之冒泡排序、快速选择排序、折半查找
- sublime text3 C语言环境配置
- [c语言]宏中##的用法(续)
- C++常用字符串函数
- [c语言]宏中 #和##的用法
- C++中指针学习记录
- MFC的运行过程分析
- lambda 表达式 c++
- 全面介绍Windows内存管理机制及C++内存分配实例
- C++中数组学习要点记录
- C语言之栈和堆(Stack && Heap)的优缺点及其使用区别
- VS2008调试C++
- 查看C++类的虚表(vtable)结构
- 关于register修饰符以及在C 与 C++中的区别
- C++ EAT / Hook
- C++类型转换
- C语言及OC语言初期学习心得
- OC语言第二课 面向对象、类、对象、方法二——ios学习连载七