寻找 ctypes Unicode 处理的“Hello World”(包括 Python 和 C 代码)
有没有人能给我一个非常简单的Python ctypes的例子,涉及到Unicode字符串还包括C语言的代码?
比如说,怎么把一个Python的Unicode字符串传给一个C语言的函数,这个函数把字符串和自己连接起来,然后把结果返回给Python,最后Python再把结果打印出来。
3 个回答
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;
}
虽然没有测试过,但我觉得这样应该可以。
s = "inputstring"
mydll.my_c_fcn.restype = c_char_p
result = mydll.my_c_fcn(s)
print result
关于内存管理,我的理解是,你的C语言代码需要自己管理它创建的内存。也就是说,不应该释放输入的字符串,但最终需要释放返回的字符串。
这个程序使用 ctypes
来从 Python 调用 wcsncat
。它将 a
和 b
合并到一个缓冲区中,这个缓冲区的长度不够放下 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