¿Cómo llama Python a la biblioteca de enlaces dinámicos de C?
La necesidad de que Python llame a bibliotecas de enlaces dinámicos C/C++
Durante el proceso de prueba automatizado, es inevitable encontrar el uso mixto de lenguajes. No, también nos hemos encontrado con esto. . Después de la decisión inicial de utilizar Robot Framework como marco de prueba automatizado, es compatible con Java y Python. Como lenguaje principal, Python, ¿cómo podemos renunciar a la oportunidad de usarlo? Sin embargo, el producto adopta la antigua estructura C/S desarrollada en la década de 1990. Debido a que era antigua, no se consideró la automatización de las pruebas del producto en ese momento. El cliente no reservó una interfaz en forma de CLI (interfaz de línea de comando). lo que realmente empeoró las cosas.
¿Cómo automatizarlo? ¿Utiliza AutoIT para automatizar las pruebas de interfaces de clientes? Desafortunadamente, AutoIT no es muy bueno para identificar los controles utilizados en el desarrollo original. Si se utiliza la ubicación del control para controlarlo, la prueba automatizada no será muy estable. ¡Entonces! ! ! La única forma de desarrollar la interfaz es desarrollar la interfaz en formato CLI en el lado del cliente, encapsularla en una DLL y luego usar Python para llamar a la DLL en el marco de Robot FrameWork. ¡Qué ardua tarea!
Ejemplo de Python llamando a DLL
Ejemplo 1
Primero, cree un proyecto DLL (lo creé en VS 2005), el archivo de encabezado:
[cpp] ver copia simple Ver el fragmento de código en CÓDIGO derivado de mi fragmento de código //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);
}
Archivo CPP:
[cpp] ver copia simple en Ver el fragmento de código en CODE y derivarlo de mi fragmento de código //hello.cpp
#define EXPORT_HELLO_DLL
#include "hello.h"
HELLO_API int IntAdd (int a, int b)
{
return a + b;
}
Hay dos puntos a tener en cuenta aquí :
(1) Descubra si la convención de llamada de función es __cdecl o __stdcall durante la compilación, porque de acuerdo con la convención de llamada de función en la DLL, Python usará la función correspondiente para cargar la DLL.
(2) Si se utiliza un proyecto C++, la interfaz exportada debe ser "C" externa para que la función exportada pueda reconocerse en Python.
En mi proyecto, uso la convención de llamada de función __cdecl para compilar y vincular para generar hello.dll, y luego uso la biblioteca ctypes en Python para cargar y llamar a la función hello.dll:
[ python] ver copia simple Ver el fragmento de código en CÓDIGO Derivado de mi fragmento de código de ctypes import *
dll = cdll.LoadLibrary('hello.dll');
ret = dll.IntAdd(2, 4);
print ret;
OK, se ha completado un pequeño ejemplo. Si está interesado pero aún no lo ha probado, entonces. Pruébalo Bar.
Ejemplo 2
El ejemplo es solo un programa de nivel "hola mundo". En la aplicación real, es necesario pasar más estructuras de datos, cadenas, etc. para satisfacer nuestras necesidades. Luego, este ejemplo mostrará cómo pasar parámetros de estructura de datos y cómo obtener el valor de retorno a través de la estructura de datos.
Primero escriba el archivo de encabezado en el proyecto DLL:
[cpp] ver copia simple Ver el fragmento de código en CODE y derivarlo a mi fragmento de código //hello.h p>
#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 número ;
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 );}
El archivo CPP es el siguiente:
[cpp] ver copia simple Ver el fragmento de código en CODE Derivado de mi fragmento de código //hello.cpp p>
#include
#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 = " hola python!";
strcpy (pStruct->str, "¡hola mundo!");
pStruct->número = 100;
return "just OK";
}
La función GetStructInfo pasa un puntero de tipo StructTest, luego asigna valores a las propiedades en el objeto y finalmente devuelve "just OK" ".
Escriba el código de llamada de Python de la siguiente manera. Primero, herede la Estructura en Python para construir una estructura de datos StructTest consistente con la DLL de C, luego establezca el tipo de parámetro y el tipo de valor de retorno de la función GetStructInfo, y finalmente cree un objeto StructTest y conviértalo en un puntero. Como parámetro, llame a la función GetStrcutInfo y finalmente verifique si la llamada fue exitosa generando el valor de la estructura de datos:
[python] vista simple. copiar Ver el fragmento de código en CODE Derivado de mi fragmento de código de ctypes import *
ARRAY_NUMBER = 20;
STR_LEN = 20;
#define type p>
INTARRAY20 = c_int * ARRAY_NUMBER;
CHARARRAY20 = c_char * STR_LEN;
#define struct
<p>clase StructTest(Estructura):
_fields_ = [
("número", c_int),
("pChar", c_char_p), p> p>
("str", CHARARRAY20),
("iArray", INTARRAY20)
]
#cargar dll y obtener el objeto de función
dll = cdll.LoadLibrary('hello.dll');
GetStructInfo = dll.GetStructInfo;
#establecer el tipo de retorno
GetStructInfo.restype = c_char_p;
#establecer los tipos de argumento
GetStructInfo.argtypes = [POINTER(StructTest)];objectStruct = StructTest();
#invocar api GetStructInfo
retStr = GetStructInfo(byref(objectStruct));#comprobar resultado
imprimir "número: ", objectStruct.number;
imprimir " pChar: ", objectStruct.pChar;
imprimir "str: ", objectStruct.str;
para i,val en enumerar(objectStruct.iArray):
print 'Array[i]: ', val;
print retStr;
Resumen
1. Utilice Python de 64 bits para cargar 32 bits. Se producirán errores de DLL de bits
2. Los anteriores son solo algunos programas de prueba. Utilice "probar excepto" tanto como sea posible para manejar las excepciones al escribir Python 3. Preste atención a los problemas de alineación de bytes cuando Python interactúa. C DLL 4. Las funciones de la biblioteca ctypes aún están por explorar