本文目录一览:
- python怎么调用c的动态链接库
- python 是否有能列出动态链接库中有哪些方法的库
- 如何把python库文件做成动态链接库
- python怎么获取动态网页链接?
- 如何让python调用C和C++代码
- 怎么调用编写好的python程序
python怎么调用c的动态链接库
Python调用C/C++动态链接库的需求 在自动化测试过程中,难免会遇到语言混合使用的情况,这不,我们也遇到了。初步决定采用Robot Framework作为自动化测试框架后,其支持Java和Python,而Python作为主流的语言,怎么能放弃使用它的机会^_^。 然而产品采用是古老90年代开发的C/S结构,因为古老,当时也没有考虑到对产品的测试进行自动化,Client端并没有预留CLI(Command Line interface)形式的接口,真是雪上加霜啊。 那怎么自动化?采用AutoIT来对客户端界面进行自动化测试?可惜AutoIT对当初开发采用的控件识别不是很好,如果采用控件所在位置来进行控制的方式,又会导致自动化测试并不是很稳定。那么!!!只有自己开发接口了,目前在Client端开发出CLI形式的接口,将其封装为DLL,然后在Robot FrameWork框架中采用Python对DLL进行调用。任务艰巨哪!
Python调用DLL例子
示例一
首先,在创建一个DLL工程(本人是在VS 2005中创建),头文件:
//hello.h
#ifdef EXPORT_HELLO_DLL
#define HELLO_API __declspec(dllexport)
#else
#define HELLO_API __declspec(dllimport)
#endif
extern "C"
{
HELLO_API int IntAdd(int , int);
}
CPP文件:
//hello.cpp
#define EXPORT_HELLO_DLL
#include "hello.h"
HELLO_API int IntAdd(int a, int b)
{
return a + b;
}
这里有两个注意点:
(1)弄清楚编译的时候函数的调用约定采用的__cdecl
还是__stdcall
,因为根据DLL中函数调用约定方式,Python将使用相应的函数加载DLL。
(2)如果采用C++的工程,那么导出的接口需要extern "C"
,这样python中才能识别导出的函数。
我的工程中采用__cdecl
函数调用约定方式进行编译链接产生hello.dll,然后Python中采用ctypes库对hello.dll进行加载和函数调用:
from ctypes import *
dll = cdll.LoadLibrary('hello.dll');
ret = dll.IntAdd(2, 4);
print ret;
OK,一个小例子已经完成了,如果你感兴趣,但还没试过,那就尝试一下吧。
示例二
示例一只是一个"hello world"级别的程序,实际运用中更多的需要传递数据结构、字符串等,才能满足我们的需求。那么这个示例将展示,如何传递数据结构参数,以及如何通过数据结构获取返回值。 首先编写DLL工程中的头文件:
//hello.h
#ifdef EXPORT_HELLO_DLL
#define HELLO_API __declspec(dllexport)
#else
#define HELLO_API __declspec(dllimport)
#endif
#define ARRAY_NUMBER 20
#define STR_LEN 20
struct StructTest
{
int number;
char* pChar;
char str[STR_LEN];
int iArray[ARRAY_NUMBER];
};
extern "C"
{
//HELLO_API int IntAdd(int , int);
HELLO_API char* GetStructInfo(struct StructTest* pStruct);
}
CPP文件如下:
//hello.cpp
#include string.h
#define EXPORT_HELLO_DLL
#include "hello.h"
HELLO_API char* GetStructInfo(struct StructTest* pStruct){
for (int i = 0; i < ARRAY_NUMBER; i++)
pStruct->iArray[i] = i;
pStruct->pChar = "hello python!";
strcpy (pStruct->str, "hello world!");
pStruct->number = 100;
return "just OK";
}
GetStructInfo这个函数通过传递一个StructTest类型的指针,然后对对象中的属性进行赋值,最后返回"just OK".
编写Python调用代码如下,首先在Python中继承Structure
构造一个和C DLL中一致的数据结构StructTest
,然后设置函数GetStructInfo
的参数类型和返回值类型,最后创建一个StructTest
对象,并将其转化为指针作为参数,调用函数GetStrcutInfo
,最后通过输出数据结构的值来检查是否调用成功:
from ctypes import *
ARRAY_NUMBER = 20;
STR_LEN = 20;
#define type
INTARRAY20 = c_int * ARRAY_NUMBER;
CHARARRAY20 = c_char * STR_LEN;
#define struct
class StructTest(Structure):
_fields_ = [
("number", c_int),
("pChar", c_char_p),
("str", CHARARRAY20),
("iArray", INTARRAY20)
]
#load dll and get the function object
dll = cdll.LoadLibrary('hello.dll');
GetStructInfo = dll.GetStructInfo;
#set the return type
GetStructInfo.restype = c_char_p;
#set the argtypes
GetStructInfo.argtypes = [POINTER(StructTest)];
objectStruct = StructTest();
#invoke api GetStructInfo
retStr = GetStructInfo(byref(objectStruct));
#check result
print "number: ", objectStruct.number;
print "pChar: ", objectStruct.pChar;
print "str: ", objectStruct.str;
for i,val in enumerate(objectStruct.iArray):
print 'Array[i]: ', val;
print retStr;
总结
- 用64位的Python去加载32位的DLL会出错
- 以上只是些测试程序,在编写Python过程中尽可能的使用"try Except"来处理异常
- 注意在Python与C DLL交互的时候字节对齐问题
- ctypes库的功能还有待继续探索
python 是否有能列出动态链接库中有哪些方法的库
最近看了《Gray hat python》一书,这才知道为什么python是黑客必学的编程语言。通过python的ctypes模块,可以直接调用动态链接库中的导出函数,而且甚至可以直接在python中构建出复杂的C结构体!!!使得python也具备了底层内存操作的能力,再配合python本身强大的表达能力,能不让人激动么。
之前为了在python中调用动态链接库导出的函数,你需要自行解析出这些导出函数的地址。而现在ctypes库会替我们完成这个麻烦的过程,大大方便了我们直接在python中调用C函数的能力。
ctypes模块中有三种不同的动态链接库加载方式:cdll
, windll
, oledll
。不同之处在于链接库中的函数所遵从的函数调用方式(calling convention)以及返回方式有所不同。
cdll
用于加载遵循cdecl标准函数调用约定的链接库。windll
则用于加载遵循stdcall调用约定的动态链接库。oledll
与windll
完全相同,只是会默认其载入的函数会统一返回一个Windows HRESULT错误编码。 先复习一下有关函数调用约定的知识:函数调用约定指的是函数参数入栈的顺序、哪些参数入栈、哪些通过寄存器传值、函数返回时栈帧的回收方式(是由调用者负责清理,还是被调用者清理)、函数名称的修饰方法等等。基本上我们最常见的调用约定就是cdecl
和stdcall
两种。在《程序员的自我修养--链接、装载与库》一书的第10章有对函数调用约定的更详细介绍。cdecl
规定函数参数列表以从右到左的方式入栈,且由函数的调用者负责清除栈帧上的参数。stdcall
的参数入栈方式与cdecl
一致,但函数返回时是由被调用者自己负责清理栈帧。而且stdcall
是Win32 API函数所使用的调用约定。OK,就这么多,够了。 测试一下在Linux平台和Windows平台下通过ctypes模块导入C库中函数的小例子: Windows 下:
from ctypes import *
msvcrt = cdll.msvcrt
msg = "Hello world!\n"
msvcrt.printf("Testing: %s", msg)
Linux下:
from ctypes import *
libc = CDLL("libc.so.6")
msg = "Hello, world!\n"
libc.printf("Testing: %s", msg)
可以看到动态链接库中的printf
被直接导入到python中来调用了。
那么,在python中怎么表示C的类型?不用担心,下面这张表就能搞定。
有了这个映射关系,多复杂的C类型也能在python中表达出来。
在C中定义一个联合:
union
{
long barley_long;
int barley_int;
char barley_char[8];
}barley_amount;
而在python中同等的定义为:注意一下python中定义数组的方式。
class barley_amount(Union):
_fields_ = [
("barley_long", c_long),
("barley_int", c_int),
("barley_char", c_char * 8),
]
测试一下这个例子,在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_int
print "Barley amount as a char: %s" % my_barley.barley_char
如何把python库文件做成动态链接库
你只能用python调用dll库,想那些底层的东西一般都是用c来写的所以下面我给您提供一个调用方式
import ctypes
dll = ctypes.WinDLL('yourDll.dll')
print dll.Sun(1+2)
print dll.count('abacadeafg',ord('a'))
python怎么获取动态网页链接?
四中方法:
得到当前页面所有连接
'''
import requests
import re
from bs4 import BeautifulSoup
from lxml import etree
from selenium import webdriver
url = ''
r = requests.get(url)
r.encoding = 'gb2312'
# 利用 re
matchs = re.findall(r"(?=href=\").+?(?=\")|(?=href=\').+?(?=\')" , r.text)
for link in matchs:
print(link)
print()
# 利用 BeautifulSoup4 (DOM树)
soup = BeautifulSoup(r.text,'lxml')
for a in soup.find_all('a'):
link = a['href']
print(link)
print()
# 利用 lxml.etree (XPath)
tree = etree.HTML(r.text)
for link in tree.xpath("//@href"):
print(link)
print()
# 利用selenium(要开浏览器!)
driver = webdriver.Firefox()
driver.get(url)
for link in driver.find_elements_by_tag_name("a"):
print(link.get_attribute("href"))
driver.close()
如何让python调用C和C++代码
Python调用C/C++
- Python调用C动态链接库 Python调用C库比较简单,不经过任何封装打包成so,再使用python的ctypes调用即可。 (1)C语言文件:pycall.c
/**
* gcc -o libpycall.so -shared -fPIC pycall.c
*/
#include <stdio.h>
#include <stdlib.h>
int foo(int a, int b)
{
printf("you input %d and %d\n", a, b);
return a + b;
}
(2)gcc编译生成动态库libpycall.so
:
gcc -o libpycall.so -shared -fPIC pycall.c
使用g++编译生成C动态库的代码中的函数或者方法时,需要使用extern "C"
来进行编译。
(3)Python调用动态库的文件:pycall.py
import ctypes
ll = ctypes.cdll.LoadLibrary
lib = ll("./libpycall.so")
lib.foo(1, 3)
print '***finish***'
(4)运行结果:
2. Python调用C++(类)动态链接库
需要extern "C"
来辅助,也就是说还是只能调用C函数,不能直接调用方法,但是能解析C方法。不是用extern "C"
,构建后的动态链接库没有这些函数的符号表。
(1)C类文件:pycallclass.cpp
#include <iostream>
using namespace std;
class TestLib
{
public:
void display();
void display(int a);
};
void TestLib::display()
{
cout << "TestLib::display()" << endl;
}
void TestLib::display(int a)
{
cout << "TestLib::display(int a)" << endl;
}
extern "C"
{
TestLib* TestLib_new() { return new TestLib(); }
void TestLib_display(TestLib* obj) { obj->display(); }
void TestLib_display_int(TestLib* obj, int a) { obj->display(a); }
}
(2)编译生成动态库:
g++ -fPIC -shared -o libpycallclass.so pycallclass.cpp
(3)Python调用动态库的文件:pycallclass.py
from ctypes import *
lib = CDLL("./libpycallclass.so")
class TestLib(Structure):
_fields_ = []
TestLib_new = lib.TestLib_new
TestLib_new.restype = POINTER(TestLib)
TestLib_display = lib.TestLib_display
TestLib_display.argtypes = [POINTER(TestLib)]
TestLib_display_int = lib.TestLib_display_int
TestLib_display_int.argtypes = [POINTER(TestLib), c_int]
obj = TestLib_new()
TestLib_display(obj)
TestLib_display_int(obj, 10)
怎么调用编写好的python程序
- 使用
os.system
函数运行其他程序 - 使用
ShellExecute
函数运行其他程序 - 使用
CreateProcess
函数运行其他程序 - 使用
ctypes
调用kernel32.dll
中的函数
1. 使用os.system
函数运行其他程序
os
模块中的system()
函数可以方便地运行其他程序或者脚本。其函数原型如下所示。
os.system(command)
其参数含义如下所示。
command
:要执行的命令,相当于在Windows的cmd窗口中输入的命令。如果要向程序或者脚本传递参数,可以使用空格分隔程序及多个参数。 以下实例实现通过os.system()
函数打开系统的记事本程序。
import os
# 使用os.system()函数打开记事本程序
os.system('notepad')
0 # 关闭记事本后的返回值
# 向记事本传递参数,打开python.txt文件
os.system('notepad python.txt')
2. 使用ShellExecute
函数运行其他程序
除了使用os
模块中的os.system()
函数以外,还可以使用win32api
模块中的ShellExecute()
函数。其函数如下所示。
ShellExecute(hwnd, op, file, params, dir, bShow)
其参数含义如下所示。
hwnd
:父窗口的句柄,如果没有父窗口,则为0。op
:要进行的操作,为“open”、“print”或者为空。file
:要运行的程序,或者打开的脚本。params
:要向程序传递的参数,如果打开的为文件,则为空。dir
:程序初始化的目录。bShow
:是否显示窗口。 以下实例使用ShellExecute
函数运行其他程序。
import win32api
# 打开记事本程序,在后台运行,即显示记事本程序的窗口
win32api.ShellExecute(0, 'open', 'notepad.exe', '', '', 0)
# 打开记事本程序,在前台运行
win32api.ShellExecute(0, 'open', 'notepad.exe', '', '', 1)
# 向记事本传递参数,打开python.txt
win32api.ShellExecute(0, 'open', 'notepad.exe', 'python.txt', '', 1)
# 在默认浏览器中打开网站
win32api.ShellExecute(0, 'open', 'http://www.example.com', '', '', 1)
# 在默认的媒体播放器中播放E:\song.wma
win32api.ShellExecute(0, 'open', 'E:\\song.wma', '', '', 1)
# 运行位于E:\book\code目录中的MessageBox.py脚本
win32api.ShellExecute(0, 'open', 'E:\\book\\code\\MessageBox.py', '', '', 1)
可以看出,使用ShellExecute
函数,就相当于在资源管理器中双击文件图标一样,系统会打开相应的应用程序执行操作。
3. 使用CreateProcess
函数运行其他程序
为了便于控制通过脚本运行的程序,可以使用win32process
模块中的CreateProcess()
函数。其函数原型如下所示。
CreateProcess(appName, commandLine, processAttributes, threadAttributes, bInheritHandles, dwCreationFlags, newEnvironment, currentDirectory, startupinfo)
其参数含义如下。
appName
:可执行的文件名。commandLine
:命令行参数。processAttributes
:进程安全属性,如果为None,则为默认的安全属性。threadAttributes
:线程安全属性,如果为None,则为默认的安全属性。bInheritHandles
:继承标志。dwCreationFlags
:创建标志。newEnvironment
:创建进程的环境变量。currentDirectory
:进程的当前目录。startupinfo
:创建进程的属性。 以下实例使用win32process.CreateProcess
函数运行记事本程序。
import win32process
win32process.CreateProcess('c:\\windows\\notepad.exe', '', None, None, 0, win32process.CREATE_NO_WINDOW, None, None, win32process.STARTUPINFO())
# 函数返回进程句柄、线程句柄、进程ID,以及线程ID
有了已创建进程的句柄就可以使用win32process.TerminateProcess
函数结束进程,或者使用win32event.WaitForSingleObject
等待创建的线程结束。其函数原型分别如下。
TerminateProcess(handle, exitCode)
WaitForSingleObject(handle, milliseconds)
对于TerminateProcess
参数含义分别如下。
handle
:要操作的进程句柄。exitCode
:进程退出代码。 对于WaitForSingleObject
参数含义分别如下。handle
:要操作的进程句柄。milliseconds
:等待的时间,如果为-1,则一直等待。 以下实例实现创建进程后并对其进行操作。
import win32process
# 打开记事本程序,获得其句柄
handle = win32process.CreateProcess('c:\\windows\\notepad.exe', '', None, None, 0, win32process.CREATE_NO_WINDOW, None, None, win32process.STARTUPINFO())
# 使用TerminateProcess函数终止记事本程序
win32process.TerminateProcess(handle[0], 0)
# 导入win32event模块
import win32event
# 创建进程获得句柄
handle = win32process.CreateProcess('c:\\windows\\notepad.exe', '', None, None, 0, win32process.CREATE_NO_WINDOW, None, None, win32process.STARTUPINFO())
# 等待进程结束
win32event.WaitForSingleObject(handle[0], -1)
# 进程结束的返回值
4. 使用ctypes
调用kernel32.dll
中的函数
使用ctypes
模块可以使Python调用位于动态链接库中的函数。在Python 2.5版中已经包含了ctypes模块。如果使用其他版本的Python,可以到网站下载安装。ctypes适用于Python 2.3版本及以上。