How Python calls the C/C ++ Dynamic Link Library
This article describes how to call the dynamic link library of C/C ++ DLL in Python using examples. The specific example is as follows:
Example 1:
First, create a DLL project (in this example, the environment is VS 2005). The header file:
//hello.h#ifdef EXPORT_HELLO_DLL#define HELLO_API __declspec(dllexport)#else#define HELLO_API __declspec(dllimport)#endifextern "C"{ HELLO_API int IntAdd(int , int);}
CPP file:
//hello.cpp#define EXPORT_HELLO_DLL#include "hello.h"HELLO_API int IntAdd(int a, int b){ return a + b;}
Note:
(1) find out whether the _ cdecl or _ stdcall function is used in the function call conventions during compilation. Because according to the function call conventions in the DLL, Python will use the corresponding function to load the DLL.
(2) If a C ++ project is used, the exported interface must be extern "C" so that the exported function can be identified in python.
In my project, the _ cdecl function call Convention is used to compile the link to generate hello. dll, and then the ctypes library is used in Python to load hello. dll and call the function:
from ctypes import *dll = cdll.LoadLibrary('hello.dll');ret = dll.IntAdd(2, 4);print ret;
Now, the first small example has been completed. You can try it yourself.
Example 2:
Example 1 is a "hello world" program. In actual use, more data structures and strings need to be transmitted to meet our needs. This example shows how to pass the data structure parameters and how to obtain the return value through the data structure.
First, compile the header file in the DLL project:
//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 20struct 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);}
The CPP file is as follows:
//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";}
The GetStructInfo function passes a StructTest pointer, assigns values to the attributes of the object, and returns "just OK ".
Compile the Python Call Code as follows. First, inherit Structure in Python to construct a consistent data Structure StructTest as in c dll, and then set the parameter type and Return Value Type of the GetStructInfo function, finally, create a StructTest object, convert it to a pointer as a parameter, call the GetStrcutInfo function, and check whether the call is successful by outputting the value of the data structure:
from ctypes import *ARRAY_NUMBER = 20;STR_LEN = 20;#define typeINTARRAY20 = c_int * ARRAY_NUMBER;CHARARRAY20 = c_char * STR_LEN;#define structclass StructTest(Structure): _fields_ = [ ("number", c_int), ("pChar", c_char_p), ("str", CHARARRAY20), ("iArray", INTARRAY20) ]#load dll and get the function objectdll = cdll.LoadLibrary('hello.dll');GetStructInfo = dll.GetStructInfo;#set the return typeGetStructInfo.restype = c_char_p;#set the argtypesGetStructInfo.argtypes = [POINTER(StructTest)];objectStruct = StructTest();#invoke api GetStructInforetStr = GetStructInfo(byref(objectStruct));#check resultprint "number: ", objectStruct.number;print "pChar: ", objectStruct.pChar;print "str: ", objectStruct.str;for i,val in enumerate(objectStruct.iArray): print 'Array[i]: ', val;print retStr;
Summary:
1. An error occurs when 32-bit DLL is loaded using 64-bit Python.
2. The above are just some test programs. try to use "try again t" to handle exceptions when writing Python.
3. Note the byte alignment problem during interaction between Python and c dll.
4. The function of the ctypes Library remains to be explored.
To solve this problem, python calls the c program dll and calls the file operation functions in the dll. Some of them are successful, while others may fail. Why?
Dll is an alternative. It seems more restrictive than the main program. In particular, the new version of windows seems to impose a lot of restrictions on DLL.
First, the problem of dynamic link database re-entry is also the Global static variable of the dynamic database (this function is canceled after 32 bits, and traffic is heavy when 16 bits are used)
Make sure that you have only one dynamic library loaded at a specific time. Then there is only one read/write operation for a specific file. Otherwise, there will be conflicts. Of course, it will fail.
How can I create a dll that can be called by python for a C program?
All dll files written in C can be called by python. python has a module named ctypes dedicated to this.