免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 8968 | 回复: 4
打印 上一主题 下一主题

python3调用c函数,怎么传入一个字符串指针在函数中对此字符串进行修改。 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-02-18 16:10 |只看该作者 |倒序浏览
前此天发了一个贴子关于怎么获得指向byte数组的指针,这个问题已得到解决。
http://bbs.chinaunix.net/thread-4125023-1-1.html
但现在出现新问题,我希望给C函数传入指针,能修改python中的数组,试了几次都没成功,希望大神帮忙。问题如下:
C函数如下:
void mytest(const unsigned char* in, const unsigned int inlen, unsigned char* out)
{

int i;
for (i = 0;i < inlen;i++)
{
        *out++ = *in++;
}

}
编译生成libfun.so

然后在python3中如下测试都没解决:

[root@kyle ~]# python3
Python 3.3.2 (default, Aug  9 2013, 11:39:3
[GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os,sys
>>> from ctypes import *
>>> packet = b'abcdefgh'
>>> libfun = cdll.LoadLibrary('./libfun.so')
>>> pinstr = c_char_p(packet)
>>> libfun.mytest("mmmm",4,byref(pinstr))
4
>>> packet
b'abcdefgh'

>>> libfun.mytest("mmmm",4,cast(packet,POINTER(c_ubyte)))
4
>>> packet
b'm\x00\x00\x00efgh'
>>> packet = b'abcdefgh'
>>> libfun.mytest("mmmm",4,cast(packet,POINTER(c_char_p)))
4
>>> packet
b'm\x00\x00\x00efgh'

>>> packet = b'abcdefgh'
>>> libfun.mytest("mmmm",4,cast(packet[2:],POINTER(c_char_p)))
>>> packet
b'abcdefgh'


>>> packet = b'abcdefgh'
>>> libfun.mytest("mmmm",4,pinstr)
段错误 (core dumped)

如上,有四个问题:
1. 墨绿色部分为啥packet值没变?
2. 如上蓝色部分字体,为啥结果为b'm\x00\x00\x00efgh',而不是想象中的b'mmmmefgh'呢
3. 对于如上红色部分字体,为啥packet值没有变化,原因我想应该在于packet[2:]的用法导致新生成了一个packet,c函数只对新生成的packet产生作用,那么我该如何来修改这段程序呢?
4. 最后为啥会core dump?

这最后问题归结为对于如何给C函数值指针不清楚,不知道byref, cast,POINTER等的用法,有哪位大神给举例解释一下,谢谢。

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
2 [报告]
发表于 2014-02-18 16:52 |只看该作者
Python的bytes和str都是不可修改的,自己创建buffer搞定。ctypes的文档就那么一点儿,读一遍就全搞定了,效率比论坛发问高得多。
  1. Python 3.3.2 (default, Feb 11 2014, 10:35:02)
  2. [GCC 4.8.2 20131212 (Red Hat 4.8.2-7)] on linux
  3. Type "help", "copyright", "credits" or "license" for more information.
  4. >>> from ctypes import *
  5. >>> libc = CDLL('libc.so.6')
  6. >>> memcpy = libc.memcpy
  7. >>> memcpy.restype = None
  8. >>> src, dst = b'abc', create_string_buffer(b'123456')
  9. >>> for e in dst: print(e)
  10. ...
  11. b'1'
  12. b'2'
  13. b'3'
  14. b'4'
  15. b'5'
  16. b'6'
  17. b'\x00'
  18. >>> memcpy(dst, src, len(src))
  19. >>> for e in dst: print(e)
  20. ...
  21. b'a'
  22. b'b'
  23. b'c'
  24. b'4'
  25. b'5'
  26. b'6'
  27. b'\x00'
复制代码

论坛徽章:
0
3 [报告]
发表于 2014-02-19 11:52 |只看该作者
谢谢楼上的指点。其实我一直想要的就是不需要创建新的buffer,而是直接在原有bytes数组上修改,但由于对于ctypes不太熟悉,文档也看了,由于缺少例程,一直没搞定,并且一直将焦点放在字符串指针从python传入c函数这个问题上。

幸运的是,今天我另写了测试程序,大胆测试了一下自己的想法,居然搞定了。如下:
c函数:

void mytest(const unsigned char* in, const unsigned int inlen, unsigned char* out)
{

int i;

for (i = 0;i < inlen;i++)
{

        *out++ = *in++;
}

}
编译生成libfun.so

然后在python3下如下执行:

[root@kyle ~]# python3
Python 3.3.2 (default, Aug  9 2013, 11:39:3
[GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os,sys
>>> from ctypes import *
>>> libfun = cdll.LoadLibrary('./libfun.so')
>>> instr = b'uvwxyz'
>>> outstr = b'abcdefgh'
>>> libfun.mytest1(instr,4,outstr)
4
>>> outstr
b'uvwxefgh'
>>> outstr = b'abcdefgh'
>>> libfun.mytest(instr,4,outstr)
4
>>> outstr
b'uvwxefgh'
>>>
意外在是,bytes居然被我给改了,并且不需要创建buffer,神奇啊。

问题是解决了,但是ctypes中相关的东东还是不太会用

论坛徽章:
0
4 [报告]
发表于 2014-02-19 11:54 |只看该作者
有大神能帮忙解释一下1楼的现象吗?

论坛徽章:
0
5 [报告]
发表于 2014-02-19 12:01 |只看该作者
1楼的问题来源于这样的一个需求:
在python3下,有一个str = b'aaaaaaaa', 本人希望能通过调用c函数将其修改为 str = b'aaeeeeee'。
其中c函数还是跟上面一样。
只是调用时是这样的:mytest(b'eeeeee',6,(char*)str+2),
不知我表达清楚了没。
因此,我就需要进行一些指针的转换,因此就有了1楼的问题。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP