在python中某些时候需要C做效率上的补充,在实际应用中,需要做部分数据的交互。使用python中的ctypes模块可以很方便的调用windows的dll(也包括linux下的so等文件),下面将详细的讲解这个模块(以windows平台为例子),当然我假设你们已经对windows下怎么写一个DLL是没有问题的。
引入ctypes库
from ctypes import *
假设你有了一个符合cdecl(这里强调调用约定是因为,stdcall调用约定和cdecl调用约定声明的导出函数,在用python加载使用的加载函数是不同的,后面会说明)调用约定的DLL(名字是add.dll),且有一个导出函数Add。
建立一个Python文件DllCall.py测试:
from
ctypes
import
*
dll
=
CDLL(
"add.dll"
)
print
dll.Add(
1
,
102
)
intPara
=
c_int(
9
)
dll.sub(
23
,
102
, byref(intPara))
print
intPara.value
# char* -- 1
szPara
=
create_string_buffer(
'\0'
*
100
)
dll.PrintInfo(byref(szPara),
100
);
print
szPara.value
# char* -- 2
sBuf
=
'aaaaaaaaaabbbbbbbbbbbbbb'
pStr
=
c_char_p( )
pStr.value
=
sBuf
#pVoid = ctypes.cast( pStr, ctypes.c_void_p ).value
dll.PrintInfo(pStr,
len
(pStr.value))
print
pStr.value
# char* -- 3
strMa
=
"\0"
*
20
FunPrint
=
dll.PrintInfo
FunPrint.argtypes
=
[c_char_p, c_int]
#FunPrint.restypes = c_void_p
nRst
=
FunPrint(strMa,
len
(strMa))
print
strMa,
len
(strMa)
# char* -- 4
pStr2
=
c_char_p(
"\0"
)
print
pStr2.value
#pVoid = ctypes.cast( pStr, ctypes.c_void_p ).value
dll.PrintInfo(pStr2,
len
(pStr.value))
print
pStr2.value
01
typedef
struct
_SimpleStruct
02
{
03
int
nNo;
04
float
fVirus;
05
char
szBuffer[512];
06
} SimpleStruct, *PSimpleStruct;
07
typedef
const
SimpleStruct* PCSimpleStruct;
08
extern
"C"
int
__declspec
(
dllexport
) PrintStruct(PSimpleStruct simp);
09
int
PrintStruct(PSimpleStruct simp)
10
{
11
printf
(
"nMaxNum=%f, szContent=%s"
, simp->fVirus, simp->szBuffer);
12
return
simp->nNo;
13
}
from
ctypes
import
*
class
SimpStruct(Structure):
_fields_
=
[ (
"nNo"
, c_int),
(
"fVirus"
, c_float),
(
"szBuffer"
, c_char
*
512
)]
dll
=
CDLL(
"AddDll.dll"
)
simple
=
SimpStruct();
simple.nNo
=
16
simple.fVirus
=
3.1415926
simple.szBuffer
=
"magicTong\0"
print
dll.PrintStruct(byref(simple))
typedef
struct
{
char
words[10];
}keywords;
typedef
struct
{
keywords *kws;
unsigned
int
len;
}outStruct;
extern
"C"
int
__declspec
(
dllexport
) test(outStruct *o);
int
test(outStruct *o)
{
unsigned
int
i = 4;
o->kws = (keywords *)
malloc
(
sizeof
(unsigned
char
) * 10 * i);
strcpy
(o->kws[0].words,
"The First Data"
);
strcpy
(o->kws[1].words,
"The Second Data"
);
o->len = i;
return
1;
}
class
keywords(Structure):
_fields_
=
[(
'words'
, c_char
*
10
),]
class
outStruct(Structure):
_fields_
=
[(
'kws'
, POINTER(keywords)),
(
'len'
, c_int),]
o
=
outStruct()
dll.test(byref(o))
print
o.kws[
0
].words;
print
o.kws[
1
].words;
print
o.
len
extern
"C"
__declspec
(
dllexport
)
char
* newGUID();
char
* newGUID()
{
static
char
buf[64] = {0};
statc GUID guid;
if
(S_OK == ::CoCreateGuid(&guid))
{
// "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"
_snprintf(buf,
sizeof
(buf),
"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"
,
guid.Data1,
guid.Data2,
guid.Data3,
guid.Data4[0], guid.Data4[1],
guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5],
guid.Data4[6], guid.Data4[7]
);
::MessageBox(NULL, buf,
"GUID"
, MB_OK);
}
return
(
char
*)buf;
}
def
CreateGUID():
"""
创建一个全局唯一标识符
类似:E06093E2-699A-4BF2-A325-4F1EADB50E18
NewVersion
"""
try
:
# dll path
strDllPath
=
sys.path[
0
]
+
str
(os.sep)
+
"createguid.dll"
dll
=
CDLL(strDllPath)
b
=
dll.newGUID()
a
=
c_char_p(b)
except
Exception, error:
print
error
return
""
return
a.value
# -*- coding:utf-8 -*-
from
ctypes
import
*
# 定义_PROCESS_INFORMATION结构体
class
_PROCESS_INFORMATION(Structure):
_fields_
=
[(
'hProcess'
, c_void_p),
(
'hThread'
, c_void_p),
(
'dwProcessId'
, c_ulong),
(
'dwThreadId'
, c_ulong)]
# 定义_STARTUPINFO结构体
class
_STARTUPINFO(Structure):
_fields_
=
[(
'cb'
,c_ulong),
(
'lpReserved'
, c_char_p),
(
'lpDesktop'
, c_char_p),
(
'lpTitle'
, c_char_p),
(
'dwX'
, c_ulong),
(
'dwY'
, c_ulong),
(
'dwXSize'
, c_ulong),
(
'dwYSize'
, c_ulong),
(
'dwXCountChars'
, c_ulong),
(
'dwYCountChars'
, c_ulong),
(
'dwFillAttribute'
, c_ulong),
(
'dwFlags'
, c_ulong),
(
'wShowWindow'
, c_ushort),
(
'cbReserved2'
, c_ushort),
(
'lpReserved2'
, c_char_p),
(
'hStdInput'
, c_ulong),
(
'hStdOutput'
, c_ulong),
(
'hStdError'
, c_ulong)]
NORMAL_PRIORITY_CLASS
=
0x00000020
# 定义NORMAL_PRIORITY_CLASS
kernel32
=
windll.LoadLibrary(
"kernel32.dll"
)
# 加载kernel32.dll
CreateProcess
=
kernel32.CreateProcessA
# 获得CreateProcess函数地址
ReadProcessMemory
=
kernel32.ReadProcessMemory
# 获得ReadProcessMemory函数地址
WriteProcessMemory
=
kernel32.WriteProcessMemory
# 获得WriteProcessMemory函数地址
TerminateProcess
=
kernel32.TerminateProcess
# 声明结构体
ProcessInfo
=
_PROCESS_INFORMATION()
StartupInfo
=
_STARTUPINFO()
fileName
=
'c:/windows/notepad.exe'
# 要进行修改的文件
address
=
0x0040103c
# 要修改的内存地址
strbuf
=
c_char_p(
"_"
)
# 缓冲区地址
bytesRead
=
c_ulong(
0
)
# 读入的字节数
bufferSize
=
len
(strbuf.value)
# 缓冲区大小
# 创建进程
CreateProcess(fileName,
0
,
0
,
0
,
0
, NORMAL_PRIORITY_CLASS,
0
,
0
, byref(StartupInfo), byref(ProcessInfo))
转自:http://www.52sky.org/73004.html