python调用打印动态链接(python调用动态链接的方法)

发布时间:2022-11-13

本文目录一览:

  1. python怎么调用c的动态链接库
  2. python 是否有能列出动态链接库中有哪些方法的库
  3. 如何把python库文件做成动态链接库
  4. python怎么获取动态网页链接?
  5. 如何让python调用C和C++代码
  6. 怎么调用编写好的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;

总结

  1. 用64位的Python去加载32位的DLL会出错
  2. 以上只是些测试程序,在编写Python过程中尽可能的使用"try Except"来处理异常
  3. 注意在Python与C DLL交互的时候字节对齐问题
  4. 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调用约定的动态链接库。
  • oledllwindll完全相同,只是会默认其载入的函数会统一返回一个Windows HRESULT错误编码。 先复习一下有关函数调用约定的知识:函数调用约定指的是函数参数入栈的顺序、哪些参数入栈、哪些通过寄存器传值、函数返回时栈帧的回收方式(是由调用者负责清理,还是被调用者清理)、函数名称的修饰方法等等。基本上我们最常见的调用约定就是cdeclstdcall两种。在《程序员的自我修养--链接、装载与库》一书的第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++

  1. 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程序

  1. 使用os.system函数运行其他程序
  2. 使用ShellExecute函数运行其他程序
  3. 使用CreateProcess函数运行其他程序
  4. 使用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版本及以上。