使用ctypes从C DLL向Python返回十六进制值遇数组访问异常求助
问题排查与修复方案
让我们一步步拆解你的代码问题,这些错误直接导致了返回值始终为-1或0:
1. 字符串比较错误(核心匹配失败原因)
在C++中,const char*类型用==比较的是指针地址,而不是字符串内容。你需要用C标准库的strcmp函数来判断字符串是否相等:
#include <cstring> // 必须包含这个头文件 // 替换原来的判断逻辑 if (strcmp(A1[i].name, needed_name) == 0) { // 匹配成功 }
2. 结构体成员访问错误
你的info_struct中style是数组类型(style_length style[MAX_SIZE]),不是指针,所以不能用->访问成员,需要用下标(比如取第一个元素style[0]):
// 原错误写法 // return A1[i].style->value; // 修正后(假设你要取数组第一个元素的value) return A1[i].style[0].value;
3. Python与C++函数名不匹配
你在C++中导出的函数是get_creation_data,但Python代码里调用的是get_section_data,这两个完全是不同的函数,导致调用失败返回默认值-1:
# 原错误代码 # valuell.get_section_data.argtypes = [c_char_p] # valuell.get_section_data.restype = ct.c_int16 # return hex(valuell.get_creation_data(value_name)) # 修正后 valuell.get_creation_data.argtypes = [c_char_p] valuell.get_creation_data.restype = ct.c_int16 return hex(valuell.get_creation_data(value_name.encode('utf-8'))) # 还要转字节串
4. 数组大小计算可能出错
你的代码中:
int A1_size = (A1size/ sizeof(A1[0])) ;
如果A1size已经是数组的元素个数(不是总字节数),那么这个计算完全错误,会导致循环次数远小于实际数组长度,直接跳过目标元素。此时应该直接用A1size作为循环上限:
// 如果A1size是元素个数 for (int i = 0; i < A1size; i++) { // ... }
如果A1size是数组的总字节数,那当前计算是对的,但需要确认A1size的实际定义是否正确。
修正后的完整代码片段
Valuedll.cpp 关键部分修正
#include <iostream> #include <string> #include <array> #include <cstring> // 新增头文件 #include "external_lists.h" extern info_struct A1[]; extern info_struct A2[]; extern int A1size; extern int A2size; #define DLLEXPORT extern "C" __declspec(dllexport) DLLEXPORT int get_creation_data(const char* needed_name){ // 确认A1size的含义:如果是元素个数,直接用A1size;如果是字节数,用A1size/sizeof(A1[0]) int A1_size = A1size; // 假设A1size是元素个数 int A2_size = A2size; for (int i = 0; i < A1_size; i++) { if (strcmp(A1[i].name, needed_name) == 0) { // 取style数组第一个元素的value return A1[i].style[0].value; } } // 再遍历A2数组 for (int i = 0; i < A2_size; i++) { if (strcmp(A2[i].name, needed_name) == 0) { return A2[i].style[0].value; } } return -1; }
Python代码修正
import os, sys, re from ctypes import * import ctypes as ct def get_creation_values(value_name): valuell = CDLL(r'C:\Documents\creation.dll') # 用原始字符串避免转义问题 valuell.get_creation_data.argtypes = [c_char_p] valuell.get_creation_data.restype = ct.c_int16 # 将Python字符串转为C兼容的字节串 return hex(valuell.get_creation_data(value_name.encode('utf-8'))) if __name__ == "__main__": val = get_creation_values('LIMITING') print(val)
额外检查点
- 确保
external_lists.h中MAX_SIZE的定义是合理的,且A1数组中style元素确实有有效值。 - 编译DLL时要确保
A1、A2、A1size、A2size被正确导出,没有链接错误。 - 如果
style_length中的value是uint16_t,C++返回int是可以的,但要注意溢出问题(不过uint16_t最大值是65535,在int范围内)。
内容的提问来源于stack exchange,提问作者Armaja LaRue-Love
相关产品推荐
相关产品推荐

