![](/img/trans.png)
[英]Python ctypes misbehaves when a C function returns a dynamic array
[英]Python ctypes function returns ValueError when C function returns NULL
I'm creating an interface to a C library in Python using ctypes, and I have a C function returns a char** (array of C-strings) normally but returns NULL on an error. 我不知道返回数组的长度,最后一个条目是 NULL。 我为 restype 尝试了多种类型:
restype = POINTER(c_char_p)
restype = POINTER(POINTER(c_char))
当 C function 成功返回时(之后处理略有不同),这两种方法都可以正常工作。 但是当 C function 出现错误并返回 NULL 时,两者都有问题。 我期望返回值是无,而是获取指向堆栈跟踪的字节字符串的指针,该指针结束“ValueError:NULL 指针访问”。
对于 C function 在成功时将 char** 转换为字符串数组但在错误时将 NULL 转换为 None 的 restype 应该是什么?
几个选项:
c_void_p
结果。 如果返回NULL
,它将被强制为None
,否则将其强制转换为POINTER(c_char_p)
以提取字符串。POINTER(c_char_p)
提取字符串。 包装一个try/except
并在ValueError
上返回None
。要么工作。 我更喜欢使用包装器来使 function 行为符合要求,并确保如果字符串是动态分配的,一旦提取为 Python 字符串,它们就会被释放。
例子:
测试.c
#if defined(_WIN32)
# define API __declspec(dllexport)
#else
# define API
#endif
#include <stdlib.h>
#include <string.h>
API char** get_strings(int fail) {
if(fail)
return NULL;
char** p = malloc(sizeof(char*) * 3);
p[0] = _strdup("test1");
p[1] = _strdup("test2");
p[2] = NULL;
return p;
}
API void free_strings(char** p) {
if(p) {
char** tmp = p;
while(*p)
free(*p++);
free(tmp);
}
}
测试.py
from ctypes import *
dll = CDLL('./test')
dll.get_strings.argtypes = c_int,
dll.get_strings.restype = POINTER(c_char_p)
dll.free_strings.argtypes = POINTER(c_char_p),
dll.free_strings.restype = None
def get_strings(fail):
p = dll.get_strings(fail)
result = []
try:
for s in p:
if s is None: break
result.append(s)
return result
except ValueError:
return None
finally:
dll.free_strings(p)
print(get_strings(0))
print(get_strings(1))
Output:
[b'test1', b'test2']
None
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.