分类: Python/Ruby
2011-04-06 08:24:03
Python ctypes
2011-4-6 磁针石 完成初稿,需要以后添加更多的实例
#承接软件自动化实施与培训等gtalk: ouyangchongwu#gmail.com qq
37391319
#python qq group: 深圳自动化测试python群:113938272
#武冈深圳qq群:66250781
参考资料:
《Gray Hat Python Python Programming for Hackers and Reverse Engineers 2009》
Python的進步: ctypes:http://blog.ez2learn.com/2009/03/21/python-evolution-ctypes/
Python:使用ctypes库调用外部DLL:http://www.cnblogs.com/wuchang/archive/2010/04/04/1704456.html
Python调用windows下DLL详解:http://blog.csdn.net/magictong/archive/2008/10/14/3075478.aspx
《python 2.7.1参考手册》
Ctypes可以调用动态链接库中的函数,可以创建复杂的c数据类型和底层内存处理工具函数。
动态链接库是主进程在执行时链接的编译二进制文件。Windows下面称为dynamic link libraries (DLL)。Linux下面叫做:shared objects (SO).。这些二进制文件,通过导出名展示函数,导出名对应着内存中的实际地址。通常运行时,你需要解析函数地址来调用函数,不过ctypes已经为你做好了这些。
Ctypes有3中不同的加载动态链接库的方法:cdll(),windll(), 和 oledll(),区别在于库中函数调用的方法和结果返回值。cdll()适用于标准cdecl调用。windll()适用于stdcall调用,是Win32 API的默认方式。oledll()和windll()类似,但是设定返回Windows HRESULT错误码,一般用于COM函数返回的错误消息。
我们来实践一下C语言中的printf()。Windows对应msvcrt.dll(C:\WINDOWS\system32\),linux对应/lib/libc.so.6
Windows代码:
from ctypes import *
msvcrt = cdll.msvcrt
message_string = "Hello world!\n"
msvcrt.printf("Testing: %s", message_string)
执行结果:
Testing: Hello world!
Linux 代码:
from ctypes import *
libc = CDLL("libc.so.6")
message_string = "Hello world!\n"
libc.printf("Testing: %s", message_string)
构建c语言的数据类型:
ctypes type |
C type |
Python type |
|
char |
1-character string |
|
wchar_t |
1-character unicode string |
|
char |
int/long |
|
unsigned char |
int/long |
|
short |
int/long |
|
unsigned short |
int/long |
|
int |
int/long |
|
unsigned int |
int/long |
|
long |
int/long |
|
unsigned long |
int/long |
|
__int64 or long long |
int/long |
|
unsigned __int64 or unsigned long long |
int/long |
|
float |
float |
|
double |
float |
|
long double |
float |
|
char * (NUL terminated) |
string or None |
|
wchar_t * (NUL terminated) |
unicode or None |
|
void * |
int/long or None |
ctypes类型可以初始化一个值:
>>> from ctypes import *
>>> c_int()
c_long(0)
>>> c_char_p("Hello world!")
c_char_p('Hello world!')
>>> c_ushort(-5)
c_ushort(65531)
>>>
>>> seitz = c_char_p("loves the python")
>>> print seitz
c_char_p('loves the python')
>>> print seitz.value
loves the python
>>> exit()
传引用只需要使用byref()函数,比如:
function_main( byref(parameter) ).
结构体的定义:
In C
struct beer_recipe
{
int amt_barley;
int amt_water;
};
In Python
class beer_recipe(Structure):
_fields_ = [
("amt_barley", c_int),
("amt_water", c_int),
]
联合中所有成员变量共享内存,可以把同一变量指定为不同类型。
In C
union {
long barley_long;
int barley_int;
char barley_char[8];
}barley_amount;
In Python
class barley_amount(Union):
_fields_ = [
("barley_long", c_long),
("barley_int", c_int),
("
见下面python实例:
from ctypes import *
class barley_amount(Union):
_fields_ = [
("barley_long", c_long),
("barley_int", c_int),
("barley_char", c_char * 8),
]
value = raw_input("Enter the amount of barley to put into the beer vat:")
my_barley = barley_amount(int(value))
print "Barley amount as a long: %ld" % my_barley.barley_long
print "Barley amount as an int: %d" % my_barley.barley_long
print "Barley amount as a char: %s" % my_barley.barley_char
执行结果:
Enter the amount of barley to put into the beer vat: 66
Barley amount as a long: 66
Barley amount as an int: 66
Barley amount as a char: B
上面实例中的barley_char演示了如何定义数组