我有一个 DLL,它分配内存,向结构中添加数据。并将数据返回给python代码。但是,在 Python 代码中获得了“空指针访问”。
C 文件:(getatt.c) --- 构建后生成 getatt.dll 文件。
typedef struct _ATTO {
char title[132 + 1];
char val[132 + 1];
} ATT;
__declspec(dllexport) void get_file_attributes(char* psFileName, ATT** *StructAtt, int* iTotalAtt) {
int j = 0;
int iError = NONE;
char cMessage[132 + 1] = "";
int iNumAtt = 5;
StructAtt = (ATT***)malloc(iNumAtt * sizeof(ATT**));
if(StructAtt == NULL) {
fprintf(stderr, "Memory allocation failed\n");
return;
}
if(iNumAtt > 0) {
for(i = 0; i < iNumAtt; i++) {
StructAtt[i] = malloc(sizeof(ATT*));
if(StructAtt[i] == NULL) {
fprintf(stderr, "Memory allocation failed\n");
return ;
}
for(j = 0; j < 1; j++) {
StructAtt[i][j] = (ATT*)malloc(sizeof(ATT));
if(StructAtt[i][j] == NULL) {
fprintf(stderr, "Memory allocation failed\n");
return ;
}
strcpy((StructAtt[i][j])->title, psStructAttInfoTitle[i]); //psStructAttInfoTitle is an array of titles
strcpy((StructAtt[i][j])->val, psStructAttInfoVal[i]); //psStructAttInfoVal is an array of values
sprintf(cMessage, "%s=%s\n", StructAtt[i][j]->title, StructAtt[i][j]->val);
// write_output(cMessage);
}
}
}
// Display values
for(i = 0; i < iNumAtt; i++) {
for(j = 0; j < 1; j++) {
sprintf(message, "%s=%s\n", (StructAtt)[i][j]->title, (StructAtt)[i][j]->val);
write_output(message);
}
}
*iTotalAtt = iNumAtt;
return;
}
结果:
TYPE=0
SUF=C
GROUP=a
OWNER=unknown
NUMSUF=467
另外,我有一个访问此函数的Python代码:
import ctypes
from ctypes import *
class PY_STRUCT(Structure):
_fields_ = [('title', c_char * 133),
('value', c_char * 133)]
file_name = 'Forest23wd'
file_att_dll = CDLL('./getatt')
file_attribute_dll.get_file_attributes.argtypes = [c_char_p, POINTER(POINTER(POINTER(PY_STRUCT))),POINTER(c_int)]
file_name_str = c_char_p(file_name.encode('utf-8'))
attr_list = POINTER(POINTER(PY_STRUCT))()
total_attr = c_int(0)
file_att_dll.get_file_attributes(file_name_str, byref(attr_list), byref(total_attr))
# Accessing data
print(total_attr.value)
print(attr_list[0][0].contents.title) # ValueError: NULL pointer access...
我得到的total_attr是5。这看起来不错。 我期待
attr_list[0][0]
会是“TYPE”。但我收到错误
ValueError: NULL pointer access.
知道我哪里做错了吗?有什么建议请留言。
您需要多一层间接。
在C代码中,需要返回
StructAtt
(一个ATT***),所以函数应该是:
__declspec(dllexport) void get_file_attributes(char* psFileName, ATT*** *pStructAtt, int* iTotalAtt) {
ATT*** StructAtt = malloc(iNumAtt * sizeof(ATT**)); // don't cast malloc in C
...
*iTotalAtt = iNumAtt;
*pStructAtt = &StructAtt;
}
然后,在 Python 中,更新
.argtypes
和 attr_list
:
file_attribute_dll.get_file_attributes.argtypes = [c_char_p, POINTER(POINTER(POINTER(POINTER(PY_STRUCT))),POINTER(c_int)]
...
attr_list = POINTER(POINTER(POINTER(PY_STRUCT)))()