python调用dll接口

文章介绍了如何在Python中使用ctypes库调用cdll接口,涉及到WindowsAPI的函数调用约定,包括对结构体ST_IMAGE的定义、指针和指针的指针操作,以及回调函数image_CallBack_PF的使用。示例代码展示了加载dll库,定义结构体,以及静态方法来调用dll中的不同功能函数。

介绍

如何在python中调用c dll接口。c dll接口会用到一些指针的指针,结构体,回调函数等,文章总结了一些常见用法。

.h 代码

#pragma once

#ifdef  __cplusplus
extern "C" {
#endif


#if defined(WIN32)  /* windows */
#define EXPORT_API                  __declspec(dllexport)
#else
#define EXPORT_API                  __declspec(dllimport)
#endif

	/* 函数标准调用约定 Standard function calling convention */
#ifdef i386
#ifndef STDCALL
#define STDCALL                 __attribute__((stdcall))
#endif
#else
#ifndef WIN32
#ifndef STDCALL
#define STDCALL
#endif
#else
#ifndef STDCALL
#define STDCALL                 __stdcall
#endif
#endif

#endif

/*
* 说明: 版本为x64版本,基于vs2019,使用前需要先安装依赖库 VC_redist15-17-19-22.x64.exe
* 中文编码格式为utf8
*/

#define IN
#define OUT
#define INOUT

struct ST_IMAGE
{
	int   int_type;  
	float float_type; 
	double double_type;  
	long long int64_type;
	char  char_type;
	unsigned char* ptr_type; 
};


typedef void (STDCALL *image_CallBack_PF)(ST_IMAGE stImage,void* pUser);


EXPORT_API void     STDCALL    interface_func_void();

EXPORT_API int      STDCALL    interface_func_int(int a);

EXPORT_API char*    STDCALL    interface_func_more_point(int a,IN char *pstr,IN ST_IMAGE image,INOUT ST_IMAGE *pimage);

EXPORT_API int    STDCALL    interface_func_pfunc_pvoid(void* handle,image_CallBack_PF pFunc,void *pUser);

EXPORT_API ST_IMAGE*  STDCALL    interface_func_more_ppoint(void **handle,IN ST_IMAGE *image);

#ifdef  __cplusplus
}
#endif  /* end of __cplusplus */


参考代码

# -*- coding: utf-8 -*-
#
# python 调用 dll 库的一些方法
#
from ctypes import *
import os

# 加载dll库所在路径到环境变量中
_lib_path = r'./'
os.environ['path'] = f'{_lib_path};' + os.environ['path']

_lib_interface = WinDLL(os.path.join(_lib_path,'py_load_dll.dll'))

winfun_ctype = WINFUNCTYPE

class _interface_image_(Structure):
    pass

ImageCallBackDef = winfun_ctype(None, _interface_image_, c_void_p)

_interface_image_._fields_ = [
        ('int_type',c_int32),
        ('float_type',c_float),
        ('double',c_double),
        ('int64_type',c_int64),
        ('char_type',c_char),
        ('ptr_type',POINTER(c_ubyte))
    ]

class dll_interface:
    def __init__(self):
        self._handle = _interface_image_()
        self.handle = pointer(self._handle)

    @staticmethod
    def interface_func_void():
        # void     STDCALL    interface_func_void();
        _lib_interface.interface_func_void()

    @staticmethod
    def interface_func_int(a:int)->int:
        _lib_interface.interface_func_int.restype = c_int32
        _lib_interface.interface_func_int.argtypes = (c_int32,)
        # int      STDCALL    interface_func_int(int a);
        return _lib_interface.interface_func_int(a)

    @staticmethod
    def interface_func_more_point(a:int,b:c_int32,msg:str,stImage,outImage)->str:
        p_b = byref(b)
        b_msg = msg.encode('gbk')
        p_image = byref(outImage)
        _lib_interface.interface_func_more_point.restype = c_char_p
        _lib_interface.interface_func_more_point.argtypes = (c_int32,c_void_p,c_void_p,_interface_image_,c_void_p)
        # char*    STDCALL    interface_func_more_point(int a,IN char *pstr,IN ST_IMAGE image,INOUT ST_IMAGE *pimage);
        return bytes.decode(_lib_interface.interface_func_more_point(a,p_b,b_msg,stImage,p_image))

    def interface_func_pfunc_pvoid(self,call_back_func,pUser)->int:
        _lib_interface.interface_func_pfunc_pvoid.restype = c_int32
        _lib_interface.interface_func_pfunc_pvoid.argtypes = (c_void_p,c_void_p,c_void_p)
        # int    STDCALL    interface_func_pfunc_pvoid(void* handle,image_CallBack_PF pFunc,void *pUser);
        # typedef void (STDCALL *image_CallBack_PF)(ST_IMAGE stImage,void* pUser);
        return _lib_interface.interface_func_pfunc_pvoid(self.handle,call_back_func,pUser)

    def interface_func_more_ppoint(self,image:_interface_image_)->pointer:
        _lib_interface.interface_func_more_ppoint.restype = c_void_p
        _lib_interface.interface_func_more_ppoint.argtypes = (c_void_p,c_void_p)
        # ST_IMAGE*  STDCALL    interface_func_more_ppoint(void **handle,IN ST_IMAGE *image);
        return _lib_interface.interface_func_more_ppoint(byref(self.handle),byref(image))


def image_callback(st_image,pUser):
    print("recv frame:",st_image.int_type,st_image.float_type,st_image.double,st_image.int64_type,pUser)

IMAGE_CALL_BACK_FUNC = ImageCallBackDef(image_callback)


if __name__ == "__main__":
    #
    dll_interface.interface_func_void()

    #
    print(dll_interface.interface_func_int(100))

    #
    inImage = _interface_image_()
    inImage.int_type = 1
    inImage.float_type = 1.1

    inOutImage = _interface_image_()
    inOutImage.int_type = 1
    inOutImage.float_type = 1.1

    b = c_int32(10)

    print(dll_interface.interface_func_more_point(1,b,"what",inImage,inOutImage))
    print(inOutImage.int_type)
    print(b.value)  # c_int32 --> int

    # interface_func_more_ppoint
    obj = dll_interface()

    p = obj.interface_func_more_ppoint(inImage)
    print(obj._handle.float_type)
    
    # void* 强制类型转换为_interface_image_
    stImage = cast(p,POINTER(_interface_image_)).contents
    print(stImage.int_type)

    # interface_func_more_ppoint
    obj.interface_func_pfunc_pvoid(IMAGE_CALL_BACK_FUNC,100)
Python调用DLL(动态链接库)接口,通常需要用到ctypes模块,它提供了一个简单的、C式的接口调用C语言编写的函数。以下是一个基本步骤: 1. 导入ctypes模块: ```python import ctypes ``` 2. 找到DLL文件路径和导入选项(头文件中的函数原型): - 确定你的DLL文件路径,例如`path_to_dll = 'your_dll.dll'` - 查看头文件(.h),找出你需要调用的函数名称、参数类型和返回类型。比如: ```c int WINAPI YourFunctionName(char* arg1, int arg2); ``` 3. 创建对应的C数据类型: ```python dll = ctypes.WinDLL(path_to_dll) # 对Windows DLL func_type = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_char_p, ctypes.c_int) # 根据头文件定义创建函数指针类型 your_function = func_type('YourFunctionName') # 替换YourFunctionName为你找到的实际函数名 ``` 4. 调用函数: ```python result = your_function('arg1_string', 42) # 将参数转换为适当的数据类型 ``` 5. 处理返回值: - 如果函数返回整型值,可以直接接收(如上例)。 - 如果有其他类型的返回值,记得处理。 注意: - 函数名、参数类型和顺序需要完全匹配头文件定义,否则可能会导致错误。 - 对于字符串参数,需要传递字符数组或使用ctypes库提供的字符串类型(如`ctypes.c_char_p`)。 这是一个基础示例,对于复杂的函数调用或者需要处理异常的情况,你可能需要编写更复杂的代码。此外,如果你的DLL包含全局变量或需要初始化,可能还需要额外的工作。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

睡在床板下_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值