使用Ctypes传递enum指针并接收uint32返回值的实现问题
ctypes传递枚举类型指针调用DLL接口的正确方法
问题背景
尝试通过Python的Ctypes库传递指向enum类型的指针来调用DLL接口,适配自有业务场景时遇到类型不匹配报错。
原DLL核心代码(C语言)
#include <stdint.h> #include <stdbool.h> #include <string.h> #include <stdlib.h> #ifdef SOME_API_EXPORTS #define SOME_API __declspec(dllexport) #else #define SOME_API __declspec(dllimport) #endif typedef enum { off, on } MyEnum; // 注:代码中error、done需提前定义,示例中省略实现 SOME_API int32_t get_param(MyEnum* param1) { int status = error; if (param1 == NULL) { return status; } // 业务处理逻辑 status = done; return status; }
初始错误实现与报错
错误Python代码
import ctypes from enum import IntEnum test = ctypes.WinDLL('Project.dll') if (test == 0): print( " Could not open DLL") class CtypesEnum(IntEnum): @classmethod def from_param(cls, obj): return int(obj) class myEnum(CtypesEnum): off = 0 on = 1 getParam = test.get_param getParam.argtypes = [ctypes.POINTER(ctypes.c_int)] getParam.restype= ctypes.c_uint getParam(myEnum.on)
报错信息
Traceback (most recent call last): File "<pyshell#5>", line 1, in <module> getParam(myEnum.on) ctypes.ArgumentError: argument 1: <class 'TypeError'>: expected LP_c_long instance instead of myEnum
错误原因
- 接口声明
argtypes = [ctypes.POINTER(ctypes.c_int)]要求传入c_int类型的指针,但代码直接传入了枚举值本身,没有封装为ctypes类型实例,也没有取指针/引用。 - 自定义的
CtypesEnum的from_param方法只适配了直接传枚举值作为值类型的场景,不满足传指针的需求。
正确实现方案
方案1:标准通用实现(兼容入参/出参场景)
如果get_param的枚举参数是入参,直接将枚举值封装为c_int实例后取引用传递即可;如果是出参,可以通过引用读取DLL修改后的枚举值:
import ctypes from enum import IntEnum # 加载DLL test = ctypes.WinDLL('./Project.dll') if not test: print("无法加载DLL文件") exit() # 定义枚举 class MyEnum(IntEnum): off = 0 on = 1 # 声明接口参数和返回值类型 get_param = test.get_param get_param.argtypes = [ctypes.POINTER(ctypes.c_int)] get_param.restype = ctypes.c_int32 # 场景1:枚举作为入参传递 param = ctypes.c_int(MyEnum.on) status = get_param(ctypes.byref(param)) print(f"调用状态:{status}") # 场景2:枚举作为出参,读取DLL返回的枚举值 out_param = ctypes.c_int() status = get_param(ctypes.byref(out_param)) print(f"调用状态:{status},返回枚举值:{MyEnum(out_param.value)}")
方案2:适配自定义枚举类的简化实现
你自行摸索的方案本质是将枚举类继承自c_int,让枚举值本身就是ctypes可识别的类型,注意修正笔误:argtype应改为复数argtypes,避免后续多参数接口出现异常:
import ctypes from ctypes import * test = ctypes.WinDLL('Project.dll') if not test: print( "无法打开DLL") exit() class myEnum(c_int): off = 0 on = 1 getParam = test.get_param # 修正笔误:argtype改为argtypes getParam.argtypes = [POINTER(myEnum)] getParam.restype= ctypes.c_int result = getParam(byref(myEnum(myEnum.on))) print(result) result = getParam(byref(myEnum(myEnum.off))) print(result)
内容的提问来源于stack exchange,提问作者pekoms
相关产品推荐
相关产品推荐

