寻找 ctypes Unicode 处理的“Hello World”(包括 Python 和 C 代码)

0 投票
3 回答
2618 浏览
提问于 2025-04-15 11:44

有没有人能给我一个非常简单的Python ctypes的例子,涉及到Unicode字符串还包括C语言的代码?

比如说,怎么把一个Python的Unicode字符串传给一个C语言的函数,这个函数把字符串和自己连接起来,然后把结果返回给Python,最后Python再把结果打印出来。

3 个回答

-1
from ctypes import *

buffer = create_string_buffer(128)
cdll.msvcrt.strcat(buffer, "blah")
print buffer.value

注意:我知道Python代码很简单,但我在C代码上遇到了困难。它需要释放输入字符串吗?它的输出字符串会被Python自动释放吗?

不,你需要手动释放这个缓冲区。通常人们会立即从buffer.value复制Python字符串,然后再释放这个缓冲区。

你能发一下C代码吗? – mike 2小时前

#include <string.h>

char* mystrcat(char* buffer) {
    strcat(buffer, "blah");
    return buffer;
}
-1

虽然没有测试过,但我觉得这样应该可以。

s = "inputstring"
mydll.my_c_fcn.restype = c_char_p
result = mydll.my_c_fcn(s)
print result

关于内存管理,我的理解是,你的C语言代码需要自己管理它创建的内存。也就是说,不应该释放输入的字符串,但最终需要释放返回的字符串。

6

这个程序使用 ctypes 来从 Python 调用 wcsncat。它将 ab 合并到一个缓冲区中,这个缓冲区的长度不够放下 a + b + (null terminator),目的是展示更安全的 n 版本的合并方法。

你必须使用 create_unicode_buffer(),而不是传递一个普通的不可变的 u"unicode string",这是因为对于非常量的 wchar_t* 参数,如果不这样做,你可能会遇到段错误。

如果你需要调用的函数返回的是 UCS-2,并且 sizeof(wchar_t) == 4,那么你就不能使用 unicode_buffer(),因为它会在 wchar_t 和 Python 内部的 Unicode 表示之间转换。在这种情况下,你可以尝试使用 result.create_string_buffer()result.decode('UCS2') 的组合,或者直接创建一个 c_short 的数组,然后用 u''.join(unichr(c) for c in buffer) 来处理。我就是这样做的,以调试一个 ODBC 驱动程序。

example.py:

#!/usr/bin/env python
#-*- encoding: utf-8 -*-
import sys
from ctypes import *
example = cdll.LoadLibrary(".libs/libexample.so")
example.its_an_example.restype = c_wchar_p
example.its_an_example.argtypes = (c_wchar_p, c_wchar_p, c_uint)
buf = create_unicode_buffer(19) # writable, unlike u"example".
buf[0] = u"\u0000"
a = u"あがぃいぅ ☃ "
b = u"個人 相命理 網上聯盟"
print example.its_an_example(buf, a, len(buf) - len(buf.value) - 1)
print example.its_an_example(buf, b, len(buf) - len(buf.value) - 1)
print buf.value # you may have to .encode("utf-8") before printing
sys.stdout.write(buf.value.encode("utf-8") + "\n")

example.c:

#include <stdlib.h>
#include <wchar.h>

wchar_t *its_an_example(wchar_t *dest, const wchar_t *src, size_t n) {
    return wcsncat(dest, src, n);
}

Makefile: (确保缩进是一个制表符,而不是空格):

all:
    libtool --mode=compile gcc -g -O -c example.c
    libtool --mode=link gcc -g -O -o libexample.la example.lo \
            -rpath /usr/local/lib

撰写回答