很抱歉,我通常很难阅读当前的ctypes文档...
如果我有一个接受const char *
指针的C函数,并且我知道它既不会修改传入的字符串,也不会在函数调用之后保留对它的引用,那么将python字符串的字节直接传递给指针真的是很合理的。
ctypes能做到这一点吗?还是说根本不支持?我真的需要create_string_buffer
并将我的字符串复制到其中吗?
给指针类型 c_char_p、c_wchar_p 和 c_void_p 的实例分配新值会更改它们所指向的内存位置,而不是内存块的内容(当然不会更改内存块的内容,因为 Python 字符串是不可变的):
>>> s = "Hello, World" >>> c_s = c_char_p(s) >>> print c_s c_char_p('Hello, World') >>> c_s.value = "Hi, there" >>> print c_s c_char_p('Hi, there') >>> print s # first string is unchanged Hello, World >>>
根据ctypes教程所说,你需要小心,不要将它们传递给期望可变内存指针的函数。如果你需要可变内存块,ctypes有一个create_string_buffer函数可以以各种方式创建这些块。如果你想将其作为以NUL结尾的字符串访问,可以使用raw属性访问(或更改)当前内存块内容,使用string属性。
由此可知,仅当函数能够使用
const char*
时,才能使用python字符串进行传递,但请注意,它不会有空终止符。无论如何,我建议还是使用
create_string_buffer
。
类型 ctypes.c_char_p 表示以空字符结尾的字符串。如果一个函数需要 const char* 类型的参数,你可以传递一个 Python 字符串给它,它将接收到一个以空字符结尾的版本。
以下是一个 Windows 的 DLL 示例:
#include <string.h>
__declspec(dllexport) char* func(char* a,size_t len,const char* b)
{
if(strlen(b) * 2 >= len)
return NULL;
strcpy_s(a,len,b);
strcat_s(a,len,b);
return a;
}
Python:
Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import *
>>> x=CDLL('x')
>>> x.func.restype=c_char_p
>>> x.func.argtypes=[c_char_p,c_int,c_char_p]
>>> s=create_string_buffer(10)
>>> x.func(s,len(s),'abcd')
'abcdabcd'
>>>
ctypes
教程中的所有示例。这些示例使用Python字符串调用printf
、strchr
等函数,并且它们将以空字符结尾。只有在需要可变字符串时才需要使用create_string_buffer
。 - Mark Tolonen