You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 08:45:00