繁体   English   中英

Python ctypes function returns ValueError when C function returns NULL

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM