【问题标题】:How do I write to string buffer from C in ctypes?如何在 ctypes 中从 C 写入字符串缓冲区?
【发布时间】:2019-03-12 18:05:45
【问题描述】:

问题

我正在尝试使用ctypes 在 Python 中使用 C 函数。函数reverse 应该将stri 的反向版本写成stro

rev.c:

#include <stddef.h>
/* length is the length of the string EXCLUDING the \0 terminator
*/
void reverse(char * stro, char * stri, size_t length)
{
    for(size_t i=0; i<length; i++) stro[i]=stri[length-1-i];
    stro[length]='\0';
}

rev.py:

from ctypes import *

revlib = cdll.LoadLibrary("rev.so");
reverse = revlib.reverse
reverse.argtypes = [c_char_p, c_char_p, c_size_t]

hello = "HelloWorld"
stri = create_string_buffer(hello)
stro = create_string_buffer(b'\000' * (len(hello)+1))

reverse(stro, stri, len(stri))

print(repr(stri.value))
print(repr(stro.value))

我用gcc -o rev.so -shared -fPIC rev.c编译了c文件,调用了export LD_LIBRARY_PATH=.,然后我尝试了上面的python脚本。这是输出:

$ python rev.py 
'HelloWorld'
''

我预计第二行是'dlroWolleH'。我避免使用空格,以防它们会引起问题。

我尝试过的

我用gcc rev.c -Wall -Wextra -std=c11 -pedantic编译了上面的c函数,它没有产生任何警告。

当我使用这个主要功能时,这个功能似乎可以工作:

int main() {
    char * str = "Hello, World";
    char o[100];
    reverse(o, str, strlen(str));
    puts(str);
    puts(o);
}

产生这个输出:

$ gcc rev.c; ./a.out 
Hello, World
dlroW ,olleH

只是为了尝试成功写入缓冲区,我尝试了sscanf,如下所示:

libc = cdll.LoadLibrary("libc.so.6")
stri = create_string_buffer(100)
libc.sscanf("HelloWorld", "%s", stri)
print(repr(stri.value))

这会打印出预期的结果。但我的函数似乎无法写入缓冲区。

我做错了什么?

【问题讨论】:

  • 在 Python 中字符串是不可变的,这意味着它们不能被改变。我建议你修改你的 C 函数以返回一个值。
  • @martineau OP 正在写入 ctypes 字符串缓冲区,而不是 Python 字符串
  • @meowgoesthedog:我意识到了。

标签: python c ctypes


【解决方案1】:

问题其实很简单。当您使用create_string_buffer 时,它会在字符串中添加一个空终止符。这意味着len(stri) 将产生一个比len(hello) 大的结果。

解决方案正在改变

reverse(stro, stri, len(stri))

reverse(stro, stri, len(stri)-1)

这是我将输入字符串更改为 'Hello, World!' 的演示:

$ python rev.py
'Hello, World!'
'!dlroW ,olleH'

【讨论】:

    猜你喜欢
    • 2021-12-11
    • 2017-08-04
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-13
    • 1970-01-01
    相关资源
    最近更新 更多