当C函数返回NULL时,Python ctypes函数返回ValueError

当C函数返回NULL时,Python ctypes函数返回ValueError,python,ctypes,Python,Ctypes,我正在用ctypes在Python中创建一个C库的接口,我有一个C函数通常返回一个char**(C字符串数组),但在出现错误时返回NULL。我不知道返回的数组的长度,最后一个条目将为NULL。我尝试了多种重新类型: restype = POINTER(c_char_p) restype = POINTER(POINTER(c_char)) 当C函数成功返回时,这两种方法都可以正常工作(之后的处理略有不同)。但是当C函数出现错误并返回NULL时,这两个函数都有问题。我希望返回值为None,但实际

我正在用ctypes在Python中创建一个C库的接口,我有一个C函数通常返回一个char**(C字符串数组),但在出现错误时返回NULL。我不知道返回的数组的长度,最后一个条目将为NULL。我尝试了多种重新类型:

restype = POINTER(c_char_p)
restype = POINTER(POINTER(c_char))
当C函数成功返回时,这两种方法都可以正常工作(之后的处理略有不同)。但是当C函数出现错误并返回NULL时,这两个函数都有问题。我希望返回值为None,但实际上是一个get指针,指向以“ValueError:NULL pointer access”结尾的堆栈跟踪的字节字符串

成功时将字符**转换为字符串数组,但错误时将NULL转换为None的C函数的重新类型应该是什么

  • 使用
    c\u void\u p
    结果。如果返回
    NULL
    ,它将被强制为
    None
    ,否则将其强制转换为
    指针(c\u char\u p)
    ,以提取字符串
  • 使用
    指针(c\u char\p)
    提取字符串。在
    try/except
    中换行,并在
    ValueError
    上返回
    None
两种方法都有效。我更喜欢使用包装器使函数按预期的方式运行,并且它可以确保如果动态分配字符串,那么一旦提取为Python字符串,它们就会被释放

例如:

test.c

#如果已定义(_WIN32)
#定义API_uudeclspec(dllexport)
#否则
#定义API
#恩迪夫
#包括
#包括
API字符**获取字符串(int失败){
如果(失败)
返回NULL;
char**p=malloc(sizeof(char*)*3);
p[0]=“测试1”);
p[1]=“测试2”);
p[2]=NULL;
返回p;
}
API无空字符串(字符**p){
如果(p){
字符**tmp=p;
而(*p)
自由(*p++);
免费(tmp);
}
}
test.py

从ctypes导入*
dll=CDLL('./测试')
dll.get_strings.argtypes=c_int,
dll.get\u strings.restype=指针(c\u char\u p)
dll.free_strings.argtypes=指针(c_char_p),
dll.free_strings.restype=None
def get_字符串(失败):
p=dll.get_字符串(失败)
结果=[]
尝试:
对于p中的s:
如果s为无:中断
结果。追加
返回结果
除值错误外:
一无所获
最后:
dll.free_字符串(p)
打印(获取字符串(0))
打印(获取字符串(1))
输出:

[b'test1',b'test2']
没有一个

我将restype切换为c_void_p,然后将其转换为POINTER(POINTER(c_char)),因为这与我之前所做的基本一致。这起作用了。我几乎想就此提交一份bug报告,我认为在我拥有的两种原始返回类型上,NULL也应该强制为None。我没有检查任何东西,它不起作用,因为那里有一些价值。