ctypes 类型 | C 类型 | Python 数据类型 |
---|---|---|
c_bool |
_Bool |
bool (1) |
c_char |
char |
单字符字节对象 |
c_wchar |
wchar_t |
单字符字符串 |
c_byte |
char |
int |
c_ubyte |
unsigned char |
int |
c_short |
short |
int |
c_ushort |
unsigned short |
int |
c_int |
int |
int |
c_uint |
unsigned int |
int |
c_long |
long |
int |
c_ulong |
unsigned long |
int |
c_longlong |
__int64 或 long long
|
int |
c_ulonglong |
unsigned __int64 或 unsigned long long
|
int |
c_size_t |
size_t |
int |
c_ssize_t |
ssize_t 或 Py_ssize_t
|
int |
c_float |
float |
float |
c_double |
double |
float |
c_longdouble |
long double |
float |
c_char_p |
char * (NUL terminated) |
字节串对象或 None
|
c_wchar_p |
wchar_t * (NUL terminated) |
字符串或 None
|
c_void_p |
void * |
int 或 None
|
在Python程序中导入ctypes模块,载入动态链接库。动态链接库有三种:cdll以及windows下的windll和oledll
- cdll载入导出函数使用标准的cdecl调用规范的库,
- windll载入导出函数符合stdcall调用规范(Win32 API的原生约定)的库
- oledll也使用stdcall调用规范,并假设函数返回Windows的HRESULT错误代码
错误代码用于在出错时自动抛出WindowsError这个Python异常,可以使用COM函数得到具体的错误信息。
使用 cdll.msvcrt
即可调用MS标准的C库msvcrt,msvcrt包含了大部分标准C函数。
下面来看一下简单的printf函数:
from ctypes import *
msvcrt = cdll.msvcrt
str = "Huanhuan!"
msvcrt.printf("Hello %s\n", str)
这样就可以使用C语言中的printf函数进行输出。
如果在IDLE里运行的话会发现程序没有任何输出结果,这是因为printf是打印到真实的标准输出,而不是sys.stdout。
如果想要看到运行结果,可以在CMD里运行python test.py来查看结果,前提是已经设置好了Python的环境变量。或者有一个曲线方法可以在IDLE中显示输出结果,请曲线阅读到文章最后。
如果使用的是Py3K,在控制台里会看到只有开头字符H被输出了。
因为Py3K使用的是Unicode编码,而printf不支持该编码,所以需要转码。
整理出来三种改写方法可以解决这一问题:
- 转为byte类型 在字符串前面加b
from ctypes import * msvcrt = cdll.msvcrt str = b"Huanhuan!" msvcrt.printf(b"Hello %s\n", str)
- 使用wprintf宽字符显示
from ctypes import * msvcrt = cdll.msvcrt str = "Huanhuan!" msvcrt.wprintf("Hello %s\n", str)
- 转码为utf-8
from ctypes import * msvcrt = cdll.msvcrt str = "Huanhuan!" result = "Hello " + str + "\n" result = result.encode("utf-8") msvcrt.printf(result)
最后来搞定在IDLE中曲线显示输出结果的方法。
from ctypes import *
msvcrt = cdll.msvcrt
str = b"Huanhuan!"
s = create_string_buffer(100) # 必须足够长
msvcrt.sprintf(s, b'Hello %s\n', str)
print(s.value.decode('utf-8'))
先使用sprintf函数把结果输出到s变量,然后再用Python自带的print方法输出s的value。
好了,通过以上的各种方法就可以解决Py3K调用C函数printf的问题了。
什么?你问我为什么费这么大劲非要用printf输出,而不是直接用Python自带的print?
python的print和c的printf有什么区别
-
print([object, ...], *, sep=' ', end='\n', file=sys.stdout, flush=False)
输出对象到流文件,sep指定分割符,end指定结束符。参数转换为字符串写入输出流,如果没有输出内容直接输出end结束符。file参数必须是包含write方法的对象,默认输出到标准输出。 -
int printf( char * format, ... );
根据参数 format 字符串来转换并格式化数据,然后将结果输出到标准输出设备(显示器),直到出现字符串结束('\0')为止。
参数 format 字符串可包含下列三种字符类型:- 一般文本,将会直接输出
- ASCII 控制字符,如
\t
、\n
等有特定含义 - 格式转换字符
格式转换为一个百分比符号(%)及其后的格式字符所组成。
一般而言,每个%符号在其后都必需有一个参数与之相呼应(只有当%%转换字符出现时会直接输出%字符),而欲输出的数据类型必须与其相对应的转换字符类型相同。
网友评论