BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / python / #20923同步于 2018/1/29
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Python机器人发帖

【问题】一个非常有意义的编写C语言扩展包的问题(有酬)

Z2012210314
2018/1/29镜像同步7 回复
近来为了给一个python程序作优化,想编写一个c语言(不是c++)的扩展包给python调用,翻了翻核心教程,发现里面只提供python里的列表 元组 字典之类的转换方法,现在的我的问题是: 我希望调用的python函数 输入是np.numpy (二维) ,输出也是numpy(一维) 我传入c函数的参数是float一维指针,还有两个long int表示二维的纬度,输出是float指针,函数依赖的库只有avx(SIMD) 那么我应该怎么样才能做到构建两者的桥梁,使用boost.python? 教程很复杂,而且也没找到float指针的转换 个人认为这应该是一个非常常见的问题,因为在python里存放大量数据必然用到numpy,想做优化的话编写c函数传入的也必然是指针,但是遗憾的是并没有发现非常便利的开源库可以非常爽的使用,有同学能赐教指点一二分享样例的话非常感谢,如果有擅长这门技巧的人自告奋勇愿意花1到2个小时(如果做过相关内容应该很顺利..?)解决这个numpy到float的桥梁搭建的话( c函数里面的实现空着即可,只需要numpy长度,地址啥的转换成float*和两个longint表示numpy的维度 ),本人愿意出一千元作为报酬,并且这个非常有意义的桥梁也可以为广大北邮同学造福,方便大家用c优化python代码,实在是一举多得,百利无害
订阅后,新回复会通过你的通知中心匿名送达。
7 条回复
lomizandtyd机器人#1 · 2018/1/29
ctypes是最简单&最快速的实现, numpy也有ctype的接口。 把你的c函数 编译成库,然后 最简单的思路就是,用argtypes = [ctypes.POINTER(ctypes.c_float), ctypes.c_long, ctypes.c_long], restype=[ctypes.POINTER(ctypes.c_float)],包装你的c函数, 再用numpy.ctypeslib作转换, 或者用numpy.ctypeslib的ndpointer 去替换上面的POINTER,直接得到numpy的数组,这样肯定最快。 stackoverflow的教程一大把。 ctypes主要是内存手动释放和c函数库编译的问题, Cython也可以,可能更加方便。示例: github -> pyworld [python wrapper for world vocoder]
yo1995机器人#2 · 2018/1/29
cython
lizz机器人#3 · 2018/1/30
我给一些语言写过大量c扩展,列一些常见的库 python:ctypesgen https://github.com/davidjamesca/ctypesgen ruby: ffi-gen https://github.com/neelance/ffi_gen Go: 直接用cgo Rust:bindgen https://github.com/rust-lang-nursery/rust-bindgen Node.js: nan https://github.com/nodejs/nan
Z2012210314机器人#4 · 2018/1/30
【 在 lomizandtyd 的大作中提到: 】 : ctypes是最简单&最快速的实现, : numpy也有ctype的接口。 : 把你的c函数 编译成库,然后 : ................... 虽然还是有点晕,但是感觉你说的很有道理,我去stackoverflow上再学习学习,谢谢老铁
Z2012210314机器人#5 · 2018/1/30
恩,我是楼主,摸爬滚打了半天终于成功了,记录一些坑,也说说ctype给我的感受: 1.首先是函数的设计,这个地方我一开始想的不好,返回值不应该存在,应该直接把某个numpy.array作为参数传入c函数,这样内存就都是python来管理,不用自己想着怎么float*转array 2.函数库的生成,这个地方也有坑,我的平台是linux,我使用了cmake生成一个共享连接库(.so结尾),生成之后我在python程序里找不到库里的函数,显示"nosymbol"的error,在xshell终端使用指令nm -Do ./*.so后,我发现连接库里的函数名都怪怪的,原因是我编译的文件后缀名是cpp,我改成c后连接库里的函数名字都变正常了,这样python程序里才找的到我要的函数 3.经过我在网上的学习,发现argtypes = [ctypes.POINTER(ctypes.c_float), ctypes.c_long, ctypes.c_long], restype=[ctypes.POINTER(ctypes.c_float)]这种包装其实是一种检查手段,如果输入函数的东西不对就会报错,但是有性能损失,所以我就没有用这个. 4.在python里输入magiclib=ct.CDLL("name.so")后,再用magicfunc=magiclib.func1 ,就得到了库里的c函数,输入参数的时候注意: numpy的对象有个.ctypes.data的属性返回首地址(值得一提的是根据我个人的调查numpy的对象生成的时候都是地址连续的,除非自己作死间隔取数),另外输入int的方法就是ct.c_int32(16) 再说说 ctypes的好处: ctypes实在是很有用,它不需要像python核心教程里一样让你去在c函数库里添加什么头文件,它的包装是站在python的视角去做的,也就是说c的库不用改。 最后提出一个疑问希望往日有人能解答: x.ctypes.data_as(POINTER(ctypes.c_float) 和x.ctypes.data到底有啥区别,有的人说有区别,但我感觉都是返回指针啊?。。。 x是一个numpy 的array
jh1机器人#6 · 2018/1/30
赞 【 在 Z2012210314 的大作中提到: 】 : 恩,我是楼主,摸爬滚打了半天终于成功了,记录一些坑,也说说ctype给我的感受: : 1.首先是函数的设计,这个地方我一开始想的不好,返回值不应该存在,应该直接把某个numpy.array作为参数传入c函数,这样内存就都是python来管理,不用自己想着怎么float*转array : 2.函数库的生成,这个地方也有坑,我的平台是linux,我使用了cmake生成一个共享连接库(.so结尾),生成之后我在python程序里找不到库里的函数,显示"nosymbol"的error,在xshell终端使用指令nm -Do ./*.so后,我发现连接库里的函数名都怪怪的,原因是我编译的文件后缀名是cpp,我改成c后连接库里的函数名字都变正常了,这样python程序里才找的到我要的函数 : ...................
Z2012210314机器人#7 · 2018/2/2
【 在 Z2012210314 的大作中提到: 】 : 恩,我是楼主,摸爬滚打了半天终于成功了,记录一些坑,也说说ctype给我的感受: : 1.首先是函数的设计,这个地方我一开始想的不好,返回值不应该存在,应该直接把某个numpy.array作为参数传入c函数,这样内存就都是python来管理,不用自己想着怎么float*转array : 2.函数库的生成,这个地方也有坑,我的平台是linux,我使用了cmake生成一个共享连接库(.so结尾),生成之后我在python程序里找不到库里的函数,显示"nosymbol"的error,在xshell终端使用指令nm -Do ./*.so后,我发现连接库里的函数名都怪怪的,原因是我编译的文件后缀名是cpp,我改成c后连接库里的函数名字都变正常了,这样python程序里才找的到我要的函数 : ................... a = np.asarray(range(16), dtype=np.int32).reshape([4,4]) if not a.flags['C_CONTIGUOUS']: a = np.ascontiguous(a, dtype=a.dtype) # 如果不是C连续的内存,必须强制转换 突然发现其实有可能内存不连续,找到解决方法贴上,愿后人少走坑