gpt4 book ai didi

python - 在 python 中使用 ctypes 从 "foreign functions"返回 NULL 指针时会发生什么?

转载 作者:行者123 更新时间:2023-11-28 18:38:49 28 4
gpt4 key购买 nike

当用 ctypes 包装 C 函数时,当一个方法返回一个 NULL 指针指向一个映射到从 ctypes.Structure 派生的 python 类的结构时会发生什么?另外,当传递给方法的有效指针设置为 NULL 值时会发生什么情况?以下测试将帮助我们找出答案:

//python_ctypes_test.c
#include <stdlib.h>

struct test_struct {
int a;
int b;
int c;
int d;
} typedef test_struct;

test_struct* get_test_struct(const int valid) {
test_struct* newStruct = 0;
if (valid > 0) {
newStruct = malloc(sizeof *newStruct);
newStruct->a = 1;
newStruct->b = 2;
newStruct->c = 3;
newStruct->d = 4;
}
return newStruct;
}

void get_two_floats(const int valid, float* float1, float* float2) {
if (valid > 0) {
*float1 = 1.1f;
*float2 = 2.2f;
} else {
float1 = 0;
float2 = 0;
}
}

#python_ctypes_test.py
import ctypes
import ctypes.util

dll = ctypes.CDLL('libpython_ctypes_test.so')

class _test_struct(ctypes.Structure):
_fields_ = [("a", ctypes.c_int),
("b", ctypes.c_int),
("c", ctypes.c_int),
("d", ctypes.c_int)]

def wrap(self, something):
self.a,self.b,self.c,self.d = something

def unwrap(self):
part1 = self.a,self.b
part2 = self.c,self.d
return part1, part2

dll.get_test_struct.restype = ctypes.POINTER(_test_struct)
dll.get_test_struct.argtypes = [ctypes.c_int]
def py_get_test_struct(valid):
return dll.get_test_struct(valid).contents.unwrap()

def py_get_test_struct_safe(valid):
testStructPtr = dll.get_test_struct(valid)
if testStructPtr:
return testStructPtr.contents.unwrap()
else:
return None

dll.get_two_floats.restype = None
dll.get_two_floats.argtypes = [ctypes.c_int,
ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float)]
def py_get_two_floats(valid):
float1_value = ctypes.c_float(0)
float1 = ctypes.pointer(float1_value)
float2_value = ctypes.c_float(0)
float2 = ctypes.pointer(float2_value)

dll.get_two_floats(valid, float1, float2)

return float1_value.value, float2_value.value

print py_get_two_floats(True)
print py_get_two_floats(False)
print py_get_test_struct_safe(True)
print py_get_test_struct_safe(False)
print py_get_test_struct(True)
print py_get_test_struct(False)

最佳答案

事实证明,开发人员无需担心已传递给函数的指针地址发生变化。

print py_get_two_floats(True)
(1.100000023841858, 2.200000047683716)

print py_get_two_floats(False)
(0.0, 0.0)

在第二种情况下,值从它们的初始化状态保持不变。这通常是正确的。如果 float1_valuefloat2_value 被初始化为 10 和 20。这些值也将保持不变。

正如@eryksun 指出的那样:

float1 and float2 are local variables that contain the address of thetwo floats. You can set the value to 0, or any other address, butthat's just changing a local variable. That's not the same asdereferencing the pointer (e.g. *float1) to access the floating pointvalue at the address.

在返回值的情况下,事情的处理方式不同。返回的对象评估为真(非空)或假(空)。

print py_get_test_struct_safe(True)
((1, 2), (3, 4))

print py_get_test_struct_safe(False)
None

尝试访问 NULL 指针会导致 ValueError 异常。

print py_get_test_struct(True)
((1, 2), (3, 4))

print py_get_test_struct(False)
Traceback (most recent call last):
File "python_ctypes.py", line 52, in <module>
print py_get_test_struct(False)
File "python_ctypes.py", line 24, in py_get_test_struct
return dll.get_test_struct(valid).contents.unwrap()
ValueError: NULL pointer access

关于python - 在 python 中使用 ctypes 从 "foreign functions"返回 NULL 指针时会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29642249/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com