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

使用ctypes实现Python调用C函数传递结构体数组的问题

问题分析与解决方案

首先需要先修正C代码中的明显错误:函数sac_dos_brute声明返回int,但实际返回的是结构体指针tab,这会导致类型不匹配。建议将返回值类型改为reference*,或者返回一个表示执行状态的整数(比如0代表成功)。

Python代码中的核心错误

  1. 结构体数组创建错误:[reference()]*2会生成两个指向同一个结构体实例的引用,修改其中一个会同步影响另一个,必须创建独立的结构体实例。
  2. 参数类型声明错误:未匹配C函数的三个参数(int, reference*, float),还存在argtype的拼写错误(正确应为argtypes)。
  3. 函数调用参数缺失:C函数需要三个参数,原代码只传递了两个,且byref(tab)的用法不符合要求。
  4. 未指定返回值类型:必须通过restype告诉ctypes如何解析C函数的返回值。

正确的Python调用代码

from ctypes import *

# 加载编译好的DLL
dll = CDLL('C:/..../workplease.dll')

# 定义与C结构体完全匹配的Python结构体类
class reference(Structure):
    _fields_ = [
        ('UID', c_int),
        ('prix', c_float),
        ('poids', c_float),
        ('quantite', c_int),
        ('nb_commande', c_int),
    ]

# 声明C函数的参数类型与返回值类型
# 注意:如果C函数返回结构体指针,将restype改为POINTER(reference)
dll.sac_dos_brute.argtypes = [c_int, POINTER(reference), c_float]
dll.sac_dos_brute.restype = c_int  # 对应C函数的返回值类型

# 创建独立的结构体实例数组
nb_produit = 2
tab = [reference() for _ in range(nb_produit)]

# 填充第一个结构体数据
tab[0].UID = 234
tab[0].prix = 12.0
tab[0].poids = 234.0
tab[0].quantite = 3
tab[0].nb_commande = 1

# 填充第二个结构体数据
tab[1].UID = 237
tab[1].prix = 15.0
tab[1].poids = 256.0
tab[1].quantite = 6
tab[1].nb_commande = 2

# 将Python结构体数组转换为C兼容的指针
tab_ptr = cast(tab, POINTER(reference))

# 调用C函数,传入完整参数
masse = 100.0  # 根据实际业务需求设置mass值
result = dll.sac_dos_brute(nb_produit, tab_ptr, masse)

# 输出C函数处理后的结构体数据(C函数可能修改了结构体内容)
for item in tab:
    print(f"UID: {item.UID}, Prix: {item.prix}, Poids: {item.poids}, Quantite: {item.quantite}, Nb Commande: {item.nb_commande}")

额外注意事项

  • 如果C代码使用MSVC编译且函数是__stdcall调用约定,需要将CDLL替换为windll。
  • 结构体的字段顺序、类型必须与C代码完全一致,否则会出现内存对齐错误,导致数据读取异常。
  • 如果C函数确实需要返回结构体指针,务必同步修改C代码的返回值声明为reference*,并将Python中的restype设置为POINTER(reference)。

内容的提问来源于stack exchange,提问作者Thibault Naud

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 09:20:26