打开 test_ctypes.py 文件,点击右上角的 Run Python File 按钮,运行 Python 脚本。
output
1 2 3 4 5 6 7 8 9
hello world in C. hello world in C. True False **************************************************************** hello world in C. hello world in C. True False
Get the current calendar time as a value of type time_t.
The function returns this value, and if the argument is not a null pointer, it also sets this value to the object pointed by timer.
The value returned generally represents the number of seconds since 00:00 hours, Jan 1, 1970 UTC (i.e., the current unix timestamp).
timer: Pointer to an object of type time_t, where the time value is stored. Alternatively, this parameter can be a null pointer, in which case the parameter is not used (the function still returns a value of type time_t with the result).
time(NULL): The value returned represents the number of seconds since 00:00 hours, Jan 1, 1970 UTC (i.e., the current unix timestamp).
在 if _name__ == '__main__': 中,注释 test_say_hello_world()。
1 2 3
#test_say_hello_world()
test_say_time(None)
打开 test_ctypes.py 文件,点击右上角的 Run Python File 按钮,运行 Python 脚本。
output
1 2
零时区时间: 9 :16 :43 北京时间: 17 :16 :43
在 ctypes 中,调用函数时可以使用 None 作为空指针。
None, integers, bytes objects and (unicode) strings are the only native Python objects that can directly be used as parameters in these function calls. None is passed as a C NULL pointer, bytes objects and strings are passed as pointer to the memory block that contains their data (char* or wchar_t*). Python integers are passed as the platforms default C int type, their value is masked to fit into the C type.
None, integers, bytes objects 和 (unicode) string 是仅有的可以直接作为函数参数使用的四种 Python 本地数据类型。None 被作为 C 的空指针(NULL),bytes objects 和 strings 是一个指向其保存数据(char* or wchar_t*)内存块指针,integers 则作为平台默认的 C 的 int 类型,它们的数值被截断以适应 C 类型的整型长度。
s = "Hello, World" c_s = ctypes.c_wchar_p(s) print(c_s) print(c_s.value)
# the memory location has changed c_s.value = "Hi, there" print(c_s) print(c_s.value)
# first object is unchanged print(s)
print("*" * 64)
print("create_string_buffer()")
# create a 3 byte buffer, initialized to NUL bytes p = ctypes.create_string_buffer(3) print(ctypes.sizeof(p), repr(p.raw))
# create a buffer containing a NUL terminated string p = ctypes.create_string_buffer(b"Hello") print(ctypes.sizeof(p), repr(p.raw)) print(repr(p.value))
# create a 10 byte buffer p = ctypes.create_string_buffer(b"hello", 10) print(ctypes.sizeof(p), repr(p.raw)) p.value = b"Hi" print(ctypes.sizeof(p), repr(p.raw))
在 if _name__ == '__main__': 中,注释 test_say_time(None)。
1 2 3
#test_say_time(None)
test_fundamental_data_types()
打开 test_ctypes.py 文件,点击右上角的 Run Python File 按钮,运行 Python 脚本。
s = "Hello, World" c_s = ctypes.c_wchar_p(s) print(c_s) print(c_s.value)
# the memory location has changed c_s.value = "Hi, there" print(c_s) print(c_s.value)
# first object is unchanged print(s)
You should be careful, however, not to pass them to functions expecting pointers to mutable memory. If you need mutable memory blocks, ctypes has a create_string_buffer() function which creates these in various ways. The current memory block contents can be accessed (or changed) with the raw property; if you want to access it as NUL terminated string, use the value property.
因此,不能将对象 c_char_p、c_wchar_p 和 c_void_p 传递给会改变指针所指内存的函数。如果想要可改变的内存块,可以使用 create_string_buffer() 函数。可以使用 raw 属性存取当前的内存块的内容。如果想要取出 NUL 结束的字符串,需要使用 value 属性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
print("create_string_buffer()")
# create a 3 byte buffer, initialized to NUL bytes p = ctypes.create_string_buffer(3) print(ctypes.sizeof(p), repr(p.raw))
# create a buffer containing a NUL terminated string p = ctypes.create_string_buffer(b"Hello") print(ctypes.sizeof(p), repr(p.raw)) print(repr(p.value))
# create a 10 byte buffer p = ctypes.create_string_buffer(b"hello", 10) print(ctypes.sizeof(p), repr(p.raw)) p.value = b"Hi" print(ctypes.sizeof(p), repr(p.raw))
This function creates a mutable character buffer. The returned object is a ctypes array of c_char.
init_or_size must be an integer which specifies the size of the array, or a bytes object which will be used to initialize the array items.
If a bytes object is specified as first argument, the buffer is made one item larger than its length so that the last element in the array is a NUL termination character. An integer can be passed as second argument which allows specifying the size of the array if the length of the bytes should not be used.
This function creates a mutable unicode character buffer. The returned object is a ctypes array of c_wchar.
init_or_size must be an integer which specifies the size of the array, or a string which will be used to initialize the array items.
If a string is specified as first argument, the buffer is made one item larger than the length of the string so that the last element in the array is a NUL termination character. An integer can be passed as second argument which allows specifying the size of the array if the length of the string should not be used.
voidcall_functions(int i, char* str, wchar_t* w_str, double db) { printf("int i = %d\nchar* str = %s\nwchar_t* w_str = %ls\ndouble* db = %f\n", i, str, w_str, db); }
生成动态链接库。
1
gcc -fPIC -shared -o libtest.so test_ctypes.c
在 test_ctypes.py 文件中,添加 test_call_functions 函数。
1 2 3 4 5 6 7 8 9 10 11 12 13
deftest_call_functions():
i = ctypes.c_int(42)
str = ctypes.c_char_p(b"Hello, World in c_char_p.")
w_str = ctypes.c_wchar_p("我要成为真正的狐狸精!!!")
db = ctypes.c_double(3.14)
libc = ctypes.CDLL("./libtest.so")
libc.call_functions(i, str, w_str, db)
在 if __name__ == '__main__': 中,注释 test_fundamental_data_types()。
1 2 3
#test_fundamental_data_types()
test_call_functions()
打开 test_ctypes.py 文件,点击右上角的 Run Python File 按钮,运行 Python 脚本。
output
1 2 3 4
int i = 42 char* str = Hello, World in c_char_p. wchar_t* w_str = 我要成为真正的狐狸精!!! double* db = 3.140000
As has been mentioned before, all Python types except integers, strings, and bytes objects have to be wrapped in their corresponding ctypes type, so that they can be converted to the required C data type
voidsay_bottles(int bottles) { printf("%d bottles of beer.\n", bottles); }
生成动态链接库。
1
gcc -fPIC -shared -o libtest.so test_ctypes.c
在 test_ctypes.py 文件中,添加 test_say_bottles 函数。
1 2 3 4 5 6 7 8 9 10 11 12 13
classBottles:
def__init__(self, number): self._as_parameter_ = number
deftest_say_bottles():
bottles = Bottles(42)
libc = ctypes.CDLL("./libtest.so")
libc.say_bottles(bottles)
在 if __name__ == '__main__': 中,注释 test_call_functions()。
1 2 3
#test_call_functions()
test_say_bottles()
打开 test_ctypes.py 文件,点击右上角的 Run Python File 按钮,运行 Python 脚本。
output
1
42 bottles of beer.
You can also customize ctypes argument conversion to allow instances of your own classes be used as function arguments. ctypes looks for an as_parameter attribute and uses this as the function argument. Of course, it must be one of integer, string, or bytes
libc.call_functions(42, b"Hello, World in c_char_p.", "我要成为真正的狐狸精!!!", 3.14)
在 if __name__ == '__main__': 中,注释 test_say_bottles()。
1 2 3
#test_say_bottles()
test_argtypes()
打开 test_ctypes.py 文件,点击右上角的 Run Python File 按钮,运行 Python 脚本。
output
1 2 3 4
int i = 42 char* str = Hello, World in c_char_p. wchar_t* w_str = 我要成为真正的狐狸精!!! double* db = 3.140000
It is possible to specify the required argument types of functions exported from DLLs by setting the argtypes attribute.
argtypes must be a sequence of C data types.
Specifying a format protects against incompatible argument types (just as a prototype for a C function), and tries to convert the arguments to valid types.
可以通过设置 argtypes 属性指定从 DLL 中导出函数的必选参数类型。
argtypes 必须是一个 C 数据类型的序列。
指定数据类型可以防止不合理的参数传递(就像 C 函数的原型),并且会自动尝试将参数转换为需要的类型。
constchar * strchr( constchar * str, int character ); char * strchr( char * str, int character );
Locate first occurrence of character in string
Returns a pointer to the first occurrence of character in the C string str.
The terminating null-character is considered part of the C string. Therefore, it can also be located in order to retrieve a pointer to the end of a string.
Parameters
str: C string.
character: Character to be located. It is passed as its int promotion, but it is internally converted back to char for the comparison.
Return Value
A pointer to the first occurrence of character in str. If the character is not found, the function returns a null pointer.
Portability
In C, this function is only declared as:
char * strchr ( const char *, int );
instead of the two overloaded versions provided in C++.
By default functions are assumed to return the C int type. Other return types can be specified by setting the restype attribute of the function object.
默认情况下都会假定函数返回 C int 类型。其他返回类型可以通过设置函数对象的 restype 属性来指定。
# c_char_p is a pointer to a string strchr.restype = ctypes.c_char_p print(strchr(b"abcdef", ord("d"))) print(strchr(b"abcdef", ord("x")))
If you want to avoid the ord(“x”) calls above, you can set the argtypes attribute, and the second argument will be converted from a single character Python bytes object into a C char.
如果希望避免上述的 ord(x) 调用,可以设置 argtypes 属性,第二个参数就会将单字符的 Python 二进制字符对象转换为 C 字符。
You can also use a callable Python object (a function or a class for example) as the restype attribute, if the foreign function returns an integer. The callable will be called with the integer the C function returns, and the result of this call will be used as the result of your function call. This is useful to check for error return values and automatically raise an exception.
如果外部函数返回了一个整数,你也可以使用一个可调用的 Python 对象(比如函数或者类)作为 restype 属性的值。将会以 C 函数返回的整数对象作为参数调用这个可调用对象,执行后的结果作为最终函数返回值。这在错误返回值校验和自动抛出异常等方面比较有用。
1 2 3 4 5 6 7 8 9 10 11
defvalid_return(value):
if value == 0: returnFalse else: returnTrue return_bool = libc.return_bool return_bool.restype = valid_return
print(return_bool())
传递指针(或以引用方式传递形参)
在 test_ctypes.c 文件中,引用 <stdio.h> 头文件。
1
#include<stdio.h>
在 test_ctypes.c 文件中,添加 pass_pointers 函数。
1 2 3 4
voidpass_pointers(int* i, float* f, char* str) { sscanf("1 3.14 Hello", "%d %f %s", i, f, str); }
生成动态链接库。
1
gcc -fPIC -shared -o libtest.so test_ctypes.c
在 test_ctypes.py 文件中,添加 test_pass_pointers 函数。
1 2 3 4 5 6 7 8 9 10
deftest_pass_pointers():
i = ctypes.c_int() f = ctypes.c_float() s = ctypes.create_string_buffer(b'\000' * 32) print(i.value, f.value, repr(s.value))
在 if __name__ == '__main__': 中,注释 test_return_types()。
1 2 3
#test_return_types()
test_pass_pointers()
打开 test_ctypes.py 文件,点击右上角的 Run Python File 按钮,运行 Python 脚本。
output
1 2
0 0.0 b'' 1 3.140000104904175 b'Hello'
1 2 3
#include<stdio.h>
intsscanf( constchar * s, constchar * format, ...);
Read formatted data from string
Reads data from s and stores them according to parameter format into the locations given by the additional arguments, as if scanf was used, but reading from s instead of the standard input (stdin).
The additional arguments should point to already allocated objects of the type specified by their corresponding format specifier within the format string.
Parameters
s: C string that the function processes as its source to retrieve the data.
format: C string that contains a format string that follows the same specifications as format in scanf (see scanf for details).
... (additional arguments): Depending on the format string, the function may expect a sequence of additional arguments, each containing a pointer to allocated storage where the interpretation of the extracted characters is stored with the appropriate type. There should be at least as many of these arguments as the number of values stored by the format specifiers. Additional arguments are ignored by the function.
Return Value
On success, the function returns the number of items in the argument list successfully filled. This count can match the expected number of items or be less (even zero) in the case of a matching failure. In the case of an input failure before any data could be successfully interpreted, EOF is returned.
1
ctypes.byref(obj[, offset])
Returns a light-weight pointer to obj, which must be an instance of a ctypes type. offset defaults to zero, and must be an integer that will be added to the internal pointer value.
byref(obj, offset) corresponds to this C code:
1
(((char *)&obj) + offset)
The returned object can only be used as a foreign function call parameter. It behaves similar to pointer(obj), but the construction is a lot faster.
Sometimes a C api function expects a pointer to a data type as parameter, probably to write into the corresponding location, or if the data is too large to be passed by value. This is also known as passing parameters by reference.
有时候 C 函数接口可能由于要往某个地址写入值,或者数据太大不适合作为值传递,从而希望接收一个指针作为数据参数类型。这可以称为引用方式传递形参。
ctypes exports the byref() function which is used to pass parameters by reference. The same effect can be achieved with the pointer() function, although pointer() does a lot more work since it constructs a real pointer object, so it is faster to use byref() if you don’t need the pointer object in Python itself.
Structures and unions must derive from the Structure and Union base classes which are defined in the ctypes module. Each subclass must define a fields attribute. fields must be a list of 2-tuples, containing a field name and a field type.
结构体和联合必须继承自 ctypes 模块中的 Structure 和 Union 。子类必须定义 _fields_ 属性。 _fields_ 是一个二元组列表,二元组中包含 field name 和 field type 。
The field type must be a ctypes type like c_int, or any other derived ctypes type: structure, union, array, pointer.
type 字段必须是一个 ctypes 类型,比如 c_int,或者其他 ctypes 类型: 结构体、联合、数组、指针。
Field descriptors can be retrieved from the class, they are useful for debugging because they can provide useful information.
可以通过类获取字段 descriptor,它能提供很多有用的调试信息。
1
print(POINT.x, POINT.y)
ctypes does not support passing unions or structures with bit-fields to functions by value. While this may work on 32-bit x86, it’s not guaranteed by the library to work in the general case. Unions and structures with bit-fields should always be passed to functions by pointer.
ctypes 不支持带位域的结构体、联合以值的方式传给函数。这可能在 32 位 x86 平台上可以正常工作,但是对于一般情况,这种行为是未定义的。带位域的结构体、联合应该总是通过指针传递给函数。
It is possible to create structures and unions containing bit fields. Bit fields are only possible for integer fields, the bit width is specified as the third item in the _fields_ tuples.
This factory function creates and returns a new ctypes pointer type. Pointer types are cached and reused internally, so calling this function repeatedly is cheap. type must be a ctypes type.
1
ctypes.pointer(obj)
This function creates a new pointer instance, pointing to obj. The returned object is of the type POINTER(type(obj)).
Note: If you just want to pass a pointer to an object to a foreign function call, you should use byref(obj) which is much faster.
Pointer instances are created by calling the pointer() function on a ctypes type.
可以将 ctypes 类型数据传入 pointer() 函数创建指针。
1 2
i = ctypes.c_int(42) pi = ctypes.pointer(i)
Pointer instances have a contents attribute which returns the object to which the pointer points, the i object above.
指针实例拥有 contents 属性,它返回指针指向的真实对象,如上面的 i 对象。
1
print(pi.contents)
Note that ctypes does not have OOR (original object return), it constructs a new, equivalent object each time you retrieve an attribute.
Pointer instances can also be indexed with integers.
指针对象也可以通过整数下标进行访问。
1
print(pi[0])
Assigning to an integer index changes the pointed to value.
通过整数下标赋值可以改变指针所指向的真实内容。
1 2 3
print(j) pi[0] = 22 print(j)
It is also possible to use indexes different from 0, but you must know what you’re doing, just as in C: You can access or change arbitrary memory locations. Generally you only use this feature if you receive a pointer from a C function, and you know that the pointer actually points to an array instead of a single item.
使用 0 以外的索引也是合法的,但是你必须确保知道自己为什么这么做,就像 C 语言中: 你可以访问或者修改任意内存内容。通常只会在函数接收指针是才会使用这种特性,而且你知道这个指针指向的是一个数组而不是单个值。
Behind the scenes, the pointer() function does more than simply create pointer instances, it has to create pointer types first. This is done with the POINTER() function, which accepts any ctypes type, and returns a new type.
This function is similar to the cast operator in C. It returns a new instance of type which points to the same memory block as obj. type must be a pointer type, and obj must be an object that can be interpreted as a pointer.
Usually, ctypes does strict type checking. This means, if you have POINTER(c_int) in the argtypes list of a function or as the type of a member field in a structure definition, only instances of exactly the same type are accepted. There are some exceptions to this rule, where ctypes accepts other objects. For example, you can pass compatible array instances instead of pointer types. So, for POINTER(c_int), ctypes accepts an array of c_int.
bar = Bar() bar.values = (ctypes.c_int * 3)(1, 2, 3) bar.count = 3 for i inrange(bar.count): print(bar.values[i])
In addition, if a function argument is explicitly declared to be a pointer type (such as POINTER(c_int)) in argtypes, an object of the pointed type (c_int in this case) can be passed to the function. ctypes will apply the required byref() conversion in this case automatically.
To set a POINTER type field to NULL, you can assign None.
可以给指针内容赋值为 None 将其设置为 Null。
1
bar.values = None
The cast() function can be used to cast a ctypes instance into a pointer to a different ctypes data type. cast() takes two parameters, a ctypes object that is or can be converted to a pointer of some kind, and a ctypes pointer type. It returns an instance of the second argument, which references the same memory block as the first argument.
Incomplete Types are structures, unions or arrays whose members are not yet specified. In C, they are specified by forward declarations, which are defined later.
不完整类型即还没有定义成员的结构体、联合或者数组。在 C 中,它们通常用于前置声明,然后在后面定义。
voidqsort(void* base, size_t num, size_t size, int (*compar)(constvoid*,constvoid*));
Sort elements of array
Sorts the num elements of the array pointed to by base, each element size bytes long, using the compar function to determine the order.
The sorting algorithm used by this function compares pairs of elements by calling the specified compar function with pointers to them as argument.
The function does not return any value, but modifies the content of the array pointed to by base reordering its elements as defined by compar.
The order of equivalent elements is undefined.
Parameters
base: Pointer to the first object of the array to be sorted, converted to a void*.
num: Number of elements in the array pointed to by base. size_t is an unsigned integral type.
size: Size in bytes of each element in the array. size_t is an unsigned integral type.
compar:
Pointer to a function that compares two elements. This function is called repeatedly by qsort to compare two elements. It shall follow the following prototype:
1
intcompar(constvoid* p1, constvoid* p2);
Taking two pointers as arguments (both converted to const void*). The function defines the order of the elements by returning (in a stable and transitive manner):
return value
meaning
<0
The element pointed to by p1 goes before the element pointed to by p2
0
The element pointed to by p1 is equivalent to the element pointed to by p2
>0
The element pointed to by p1 goes after the element pointed to by p2
For types that can be compared using regular relational operators, a general compar function may look like:
1 2 3 4 5 6
intcompareMyType(constvoid * a, constvoid * b) { if ( *(MyType*)a < *(MyType*)b ) return-1; if ( *(MyType*)a == *(MyType*)b ) return0; if ( *(MyType*)a > *(MyType*)b ) return1; }
The returned function prototype creates functions that use the standard C calling convention. The function will release the GIL during the call.
ctypes allows creating C callable function pointers from Python callables. These are sometimes called callback functions.
ctypes 允许创建一个指向 Python 可调用对象的 C 函数。它们有时候被称为回调函数。
First, you must create a class for the callback function. The class knows the calling convention, the return type, and the number and types of arguments this function will receive. The CFUNCTYPE() factory function creates types for callback functions using the cdecl calling convention.
Both of these factory functions are called with the result type as first argument, and the callback functions expected argument types as the remaining arguments.
I will present an example here which uses the standard C library’s qsort() function, that is used to sort items with the help of a callback function. qsort() will be used to sort an array of integers.
这些工厂函数的第一个参数是返回值类型,回调函数的参数类型作为剩余参数。这里展示一个使用 C 标准库函数 qsort() 的例子,它使用一个回调函数对数据进行排序。qsort() 将用来给整数数组排序。
qsort() must be called with a pointer to the data to sort, the number of items in the data array, the size of one item, and a pointer to the comparison function, the callback. The callback will then be called with two pointers to items, and it must return a negative integer if the first item is smaller than the second, a zero if they are equal, and a positive integer otherwise.
classctypes._CData # This non-public class is the common base class of all ctypes data types. in_dll(library, name) # This method returns a ctypes type instance exported by a shared library. name is the name of the symbol that exports the data, library is the loaded shared library.
Some shared libraries not only export functions, they also export variables. ctypes can access values like this with the in_dll() class methods of the type.
# now swap the two points rc.upperleft, rc.lowerright = rc.lowerright, rc.upperleft print(rc.upperleft.x, rc.upperleft.y, rc.lowerright.x, rc.lowerright.y)
print("*" * 64)
s = ctypes.c_char_p() s.value = b"abc def ghi" print(s.value) print(s.value is s.value)
在 if __name__ == '__main__': 中,注释 test_access_values_from_dlls()。
1 2 3
#test_access_values_from_dlls()
test_surprises()
打开 test_ctypes.py 文件,点击右上角的 Run Python File 按钮,运行 Python 脚本。
# now swap the two points rc.upperleft, rc.lowerright = rc.lowerright, rc.upperleft print(rc.upperleft.x, rc.upperleft.y, rc.lowerright.x, rc.lowerright.y)
Hm. We certainly expected the last statement to print 3 4 1 2. What happened? Here are the steps of the rc.a, rc.b = rc.b, rc.a line above.
Note that temp0 and temp1 are objects still using the internal buffer of the rc object above. So executing rc.a = temp0 copies the buffer contents of temp0 into rc ‘s buffer. This, in turn, changes the contents of temp1. So, the last assignment rc.b = temp1, doesn’t have the expected effect.
Keep in mind that retrieving sub-objects from Structure, Unions, and Arrays doesn’t copy the sub-object, instead it retrieves a wrapper object accessing the root-object’s underlying buffer.
s = ctypes.c_char_p() s.value = b"abc def ghi" print(s.value) print(s.value is s.value)
使用 c_char_p 实例化的对象只能将其值设置为 bytes 或者整数。
Why is it printing False? ctypes instances are objects containing a memory block plus some descriptors accessing the contents of the memory. Storing a Python object in the memory block does not store the object itself, instead the contents of the object is stored. Accessing the contents again constructs a new Python object each time!
在 if __name__ == '__main__': 中,注释 test_surprises()。
1 2 3
#test_surprises()
test_variable_sized_data_types()
打开 test_ctypes.py 文件,点击右上角的 Run Python File 按钮,运行 Python 脚本。
output
1 2 3 4 5
8 8 32 8 [0, 0, 0, 0]
1
ctypes.resize(obj, size)
This function resizes the internal memory buffer of obj, which must be an instance of a ctypes type. It is not possible to make the buffer smaller than the native size of the objects type, as given by sizeof(type(obj)), but it is possible to enlarge the buffer.
ctypes provides some support for variable-sized arrays and structures.
在 if __name__ == '__main__': 中,注释 test_variable_sized_data_types()。
1 2 3
#test_variable_sized_data_types()
test_from_buffer_copy()
打开 test_ctypes.py 文件,点击右上角的 Run Python File 按钮,运行 Python 脚本。
output
1
0 1 2 3 4 5 6 7 8 9
1 2 3 4 5
classctypes._CData # This non-public class is the common base class of all ctypes data types. from_buffer_copy(source[, offset]) # This method creates a ctypes instance, copying the buffer from the source object buffer which must be readable. The optional offset parameter specifies an offset into the source buffer in bytes; the default is zero.
Copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point).
To avoid overflows, the size of the array pointed by destination shall be long enough to contain the same C string as source (including the terminating null character), and should not overlap in memory with source.
Parameters
destination: Pointer to the destination array where the content is to be copied.
intsprintf( char * str, constchar * format, ... );
Write formatted data to string
Composes a string with the same text that would be printed if format was used on printf, but instead of being printed, the content is stored as a C string in the buffer pointed by str.
The size of the buffer should be large enough to contain the entire resulting string (see snprintf for a safer version).
A terminating null character is automatically appended after the content.
After the format parameter, the function expects at least as many additional arguments as needed for format.
Parameters
str: Pointer to a buffer where the resulting C-string is stored. The buffer should be large enough to contain the resulting string.
format: C string that contains a format string that follows the same specifications as format in printf (see printf for details).
... (additional arguments): Depending on the format string, the function may expect a sequence of additional arguments, each containing a value to be used to replace a format specifier in the format string (or a pointer to a storage location, for n). There should be at least as many of these arguments as the number of values specified in the format specifiers. Additional arguments are ignored by the function.
Return Value
On success, the total number of characters written is returned. This count does not include the additional null-character automatically appended at the end of the string. On failure, a negative number is returned.
s = "Hello, World" c_s = ctypes.c_wchar_p(s) print(c_s) print(c_s.value)
# the memory location has changed c_s.value = "Hi, there" print(c_s) print(c_s.value)
# first object is unchanged print(s)
print("*" * 64)
print("create_string_buffer()")
# create a 3 byte buffer, initialized to NUL bytes p = ctypes.create_string_buffer(3) print(ctypes.sizeof(p), repr(p.raw))
# create a buffer containing a NUL terminated string p = ctypes.create_string_buffer(b"Hello") print(ctypes.sizeof(p), repr(p.raw)) print(repr(p.value))
# create a 10 byte buffer p = ctypes.create_string_buffer(b"hello", 10) print(ctypes.sizeof(p), repr(p.raw)) p.value = b"Hi" print(ctypes.sizeof(p), repr(p.raw))
deftest_call_functions():
i = ctypes.c_int(42)
str = ctypes.c_char_p(b"Hello, World in c_char_p.")
w_str = ctypes.c_wchar_p("我要成为真正的狐狸精!!!")
db = ctypes.c_double(3.14)
libc = ctypes.CDLL("./libtest.so")
libc.call_functions(i, str, w_str, db)
classBottles:
def__init__(self, number): self._as_parameter_ = number
# now swap the two points rc.upperleft, rc.lowerright = rc.lowerright, rc.upperleft print(rc.upperleft.x, rc.upperleft.y, rc.lowerright.x, rc.lowerright.y)
print("*" * 64)
s = ctypes.c_char_p() s.value = b"abc def ghi" print(s.value) print(s.value is s.value)