如何在Swift 5中调用可变参数C函数evolis_get_devices?
解决Swift 5调用C可变参数函数
evolis_get_devices的不可用问题 问题分析
你遇到的'evolis_get_devices' is unavailable: Variadic function is unavailable错误,根源是Swift对C风格的可变参数函数(带...语法)支持有限,无法直接调用。结合C函数的注释“Takes a list of model ended by zero”,该函数的可变参数需要传入一系列设备模型标识,最后以0结尾,而非你当前传入的count变量——实际上count是函数的返回值,用于获取设备数量。
解决方案
方法1:C封装层中转(推荐)
通过编写简单的C封装函数,将可变参数转换为固定参数形式,是最稳妥的解决方式,避免Swift与C可变参数的兼容性问题。
创建C封装文件:
- 头文件
EvolisWrapper.h:#include "evolis_sdk.h" // 引入原Evolis SDK头文件 EVOLIS_LIB int evolis_get_devices_wrapper(evolis_device_t** devices); - 实现文件
EvolisWrapper.c:#include "EvolisWrapper.h" int evolis_get_devices_wrapper(evolis_device_t** devices) { // 传入0作为可变参数结尾,获取所有设备(如需指定模型,可替换为对应标识,如"PM40", 0) return evolis_get_devices(devices, 0); }
- 头文件
Swift中调用封装后的函数:
public static func getDevices() -> [Device] { var devices: UnsafeMutablePointer<evolis_device_t>? let count = evolis_get_devices_wrapper(&devices) var devicesList: [Device] = [] if count > 0 { for i in 0..<count { let device = Device(device_c: devices![Int(i)]) devicesList.append(device) } } evolis_free_devices(devices) return devicesList }
方法2:使用Swift的withVaList(兼容性差,不推荐)
如果不想新增C文件,可以尝试用Swift的withVaList构造可变参数列表,但这种方式对C函数的参数要求严格,且跨版本兼容性不佳:
public static func getDevices() -> [Device] { var devices: UnsafeMutablePointer<evolis_device_t>? var count: Int32 = 0 // 构造以0结尾的可变参数列表 withVaList([0]) { vaList in count = evolis_get_devices(&devices, vaList) } var devicesList: [Device] = [] if count > 0 { for i in 0..<count { let device = Device(device_c: devices![Int(i)]) devicesList.append(device) } } evolis_free_devices(devices) return devicesList }
注意事项
- 原C函数的
count是返回值,不是传入参数,你之前的代码逻辑存在错误,需要修正。 - 若需指定特定设备模型,可在C封装函数的
evolis_get_devices调用中传入对应模型字符串,最后以0结尾,例如evolis_get_devices(devices, "PM40", "Zenius", 0)。
内容的提问来源于stack exchange,提问作者nemoxi
相关产品推荐
相关产品推荐

