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

2024-07-08 11:02:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用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”结尾的堆栈跟踪的字节字符串

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


Tags: 方法函数字符串none类型get错误条目
1条回答
网友
1楼 · 发布于 2024-07-08 11:02:13

有两种选择:

  • 使用c_void_p结果。如果返回NULL,它将被强制为None,否则将其强制转换为POINTER(c_char_p)以提取字符串
  • 使用POINTER(c_char_p)提取字符串。用try/except换行并在ValueError上返回None

两种方法都有效。我更喜欢使用包装器使函数按预期的方式运行,并且它可以确保如果动态分配字符串,那么一旦提取为Python字符串,它们就会被释放

例如:

test.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);
    }
}

test.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))

输出:

[b'test1', b'test2']
None

相关问题 更多 >

    热门问题