如何用Python+ctypes处理Fanuc CNC C库异构数据结构并输出JSON?
解决方案:用ctypes映射Fanuc ODBDY2结构体并转JSON
1. 用ctypes定义对应C结构体
直接根据ODBDY2的typedef定义ctypes结构体,替代手动拆分uint32数组,从根源解决数据类型解析问题:
import ctypes import json # 严格对应C语言中的ODBDY2结构体定义(字段顺序、类型必须完全匹配) class ODBDY2(ctypes.Structure): _fields_ = [ # 前两个2字节short类型字段(根据实际符号调整c_int16/c_uint16) ("field1", ctypes.c_uint16), ("field2", ctypes.c_uint16), # 剩余4字节long类型字段(根据实际符号调整c_int32/c_uint32) ("field3", ctypes.c_uint32), ("field4", ctypes.c_uint32), # 补充剩余所有字段,确保和C结构体字段数量、顺序一致 # ... ]
注意:必须严格匹配C结构体的字段顺序、符号属性,否则会出现内存解析错误
2. 调用C库填充结构体数据
替换原来的(ctypes.c_uint32 * 11)()数组方式,直接用结构体实例接收数据:
# 加载Fanuc的C库(Windows下替换为.dll路径) fanuc_c_lib = ctypes.CDLL("/path/to/fanuc_c_library.so") # 声明C函数的参数和返回类型(关键:确保参数类型匹配) fanuc_c_lib.your_fanuc_function.argtypes = [ctypes.POINTER(ODBDY2)] fanuc_c_lib.your_fanuc_function.restype = ctypes.c_int # 根据实际返回值调整 # 创建结构体实例并传入函数 data_struct = ODBDY2() ret_code = fanuc_c_lib.your_fanuc_function(ctypes.byref(data_struct)) # 检查函数返回码(根据Fanuc库的错误码规则处理异常) if ret_code != 0: # 错误处理逻辑 pass
3. 结构体转字典再转JSON
写一个通用工具函数将ctypes结构体转为Python字典,再直接序列化为JSON供Flask接口返回:
def struct_to_dict(struct_instance): """将ctypes结构体转为Python字典""" return {field: getattr(struct_instance, field) for field, _ in struct_instance._fields_} # 转为字典 data_dict = struct_to_dict(data_struct) # Flask接口直接返回(jsonify可直接接收字典) from flask import Flask, jsonify app = Flask(__name__) @app.route("/fanuc/odbdy2") def get_odbdy2_data(): # 复用上述结构体填充逻辑 return jsonify(data_dict)
4. 批量处理300+类似结构体
针对大量同模式结构体,可写一个动态生成结构体类的工具函数,避免重复手写:
def generate_fanuc_struct(struct_name, short_field_num, long_field_num, signed=True): """ 动态生成Fanuc风格结构体类 :param struct_name: 结构体名称 :param short_field_num: 2字节short字段数量 :param long_field_num: 4字节long字段数量 :param signed: 是否为有符号类型 """ short_type = ctypes.c_int16 if signed else ctypes.c_uint16 long_type = ctypes.c_int32 if signed else ctypes.c_uint32 fields = [] # 添加short字段 for i in range(short_field_num): fields.append((f"short_{i+1}", short_type)) # 添加long字段 for i in range(long_field_num): fields.append((f"long_{i+1}", long_type)) return type(struct_name, (ctypes.Structure,), {"_fields_": fields}) # 示例:生成ODBDY2结构体(2个无符号short,10个无符号long) ODBDY2 = generate_fanuc_struct("ODBDY2", 2, 10, signed=False)
内容的提问来源于stack exchange,提问作者Developer Gee
相关产品推荐
相关产品推荐

