Python调用DLL



环境: VS2010 + Python27


一. 创建一个dll


DLL的创建过程参考: http://blog.csdn.net/cay22/article/details/5391319


1. 这里dll中导出函数是使用__stdcall声明的.
2. TestDll.dll中的两个导出函数
// TestDll.h

#pragma once

#ifdef __cplusplus
extern "C"{
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////
struct STPerson
{  
    int m_nAge;
    char m_chName[50];
    char* m_pDis;
    int m_nList[50];
};

int __stdcall GetSTPersonInfo(struct STPerson* pSTPerson);

int __stdcall MyAdd(int nA, int nB);

/////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
}
#endif

// TestDll.cpp

// TestDll.cpp : 定义 DLL 应用程序的导出函数。
//

#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#include "TestDll.h"

#ifdef __cplusplus
extern "C"{
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////
int __stdcall MyAdd(int nA, int nB)
{
    return nA + nB;
}

int __stdcall GetSTPersonInfo(struct STPerson* pSTPerson)
{
	pSTPerson->m_nAge = 80;
	int i = 0;
	for(i = 0; i < 50; ++i)
	{
		pSTPerson->m_nList[i] = 2 * i;
	}
	strcpy(pSTPerson->m_chName, "Bluce");
    pSTPerson->m_pDis = "const string";
    return 1;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
}
#endif


二. Python调用DLL


2.1 最简单的调用代码


#-*- coding:utf-8 -*-
import ctypes

# 导出函数是__stdcall声明的使用
dll = ctypes.windll.LoadLibrary("TestDll.dll");
# 导出函数是__cdecl声明的使用
# dll = ctypes.cdll.LoadLibrary("TestDll.dll");

ret = dll.MyAdd(2, 4);
print ret;


2.2 传递数据结构的调用

#-*- coding:utf-8 -*-
import ctypes

# 定义对应C++的数据结构
class STPerson(ctypes.Structure):
	_fields_ = [
		("m_nAge", ctypes.c_int),
		("m_chName", ctypes.c_char * 50),
        ("m_pDis", ctypes.c_char_p),
        ("m_nList", ctypes.c_int * 50)
    ]

# 导出函数是__stdcall声明的使用
dll = ctypes.windll.LoadLibrary("TestDll.dll");
# 导出函数是__cdecl声明的使用
# dll = ctypes.cdll.LoadLibrary("TestDll.dll");

# 最简单调用
ret = dll.MyAdd(2, 4);
print ret;

# 传递数据结构的调用
# 设置返回值类型 
dll.GetSTPersonInfo.restype = ctypes.c_int;  
# 设置参数列表(每个参数的类型)
dll.GetSTPersonInfo.argtypes = [ctypes.POINTER(STPerson)];  
  
objectStruct = STPerson();
# 调用GetSTPersonInfo函数
nResult = dll.GetSTPersonInfo(ctypes.byref(objectStruct));  
  
# 输出调用结果
print "m_nAge: ", objectStruct.m_nAge;  
print "m_chName: ", objectStruct.m_chName;  
print "m_pDis: ", objectStruct.m_pDis;  
for i, val in enumerate(objectStruct.m_nList):  
    print 'm_nList[i]:', val;  
print nResult;


三. 小结


1. 这里主要是使用Python中的ctypes库
2. 在使用C++的数据结构时, Python一定要对应好, 说白了Python就是把数据结构的内存传递给DLL.
3. 所以要注意传递数据的内存对齐问题.
4. 对应C++的Python数据结构继承ctypes.Structure
5. 从上面代码可以看到, Python这样子调用DLL有一点脆弱哦, 随便一个类型没对上, 程序就会崩溃的.
6. 熟悉ctypes才能更好掌握Python调用DLL.
参考这个:
https://docs.python.org/2/library/ctypes.html
7. ctypes和C的类型对应表

ctypes defines a number of primitive C compatible data types:

ctypes type C type Python type
c_bool _Bool bool (1)
c_char char 1-character string
c_wchar wchar_t 1-character unicode string
c_byte char int/long
c_ubyte unsigned char int/long
c_short short int/long
c_ushort unsigned short int/long
c_int int int/long
c_uint unsigned int int/long
c_long long int/long
c_ulong unsigned long int/long
c_longlong __int64 or long long int/long
c_ulonglong unsigned __int64 or unsigned long long int/long
c_float float float
c_double double float
c_longdouble long double float
c_char_p char * (NUL terminated) string or None
c_wchar_p wchar_t * (NUL terminated) unicode or None
c_void_p void * int/long or None


四. 注意


4.1. 这里的调用dll是Python直接调用dll, 被调用的dll并不知道调用它的是什么语言.
4.2. Python有它自己的扩展框架, 我们可以按照Python规定的扩展框架来扩展Python的功能. 而这种扩展也是通过动态库实现(Window下是*.dll文件, Linux下是*.o文件)
4.3. 实现扩展功能的DLL与上面的DLL调用是有区别的, 扩展功能的DLL必须按照Python的扩展框架实现指定的接口(所以这个需要区分简单的dll调用).


你可能感兴趣的:(C++,python,dll,调用)