gpt4 book ai didi

python - 将列表从 Python 传递到 C,列表值在处理后未更新

转载 作者:太空宇宙 更新时间:2023-11-03 19:57:00 25 4
gpt4 key购买 nike

这里是示例 C 代码:

#include <stdint.h>

struct Pixel {
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
};

void normalize(struct Pixel *img, uint32_t num, uint8_t r_mean, uint8_t g_mean, uint8_t b_mean)
{
for (uint32_t i = 0; i < num; ++i) {
img[i].r -= r_mean;
img[i].g -= g_mean;
img[i].b -= b_mean;
}
}

和Python代码:

import ctypes

class Pixel(ctypes.Structure):
_fields_ = [('r', ctypes.c_ubyte),
('g', ctypes.c_ubyte),
('b', ctypes.c_ubyte),
('a', ctypes.c_ubyte)]


pixels = [Pixel(255, 255, 255, 0), Pixel(128, 128, 128, 0), Pixel(0, 128, 128, 0)]
pixels_num = len(pixels)
mean = 100

print('original pixels:', pixels)
for pixel in pixels:
print(pixel.r, pixel.g, pixel.b, pixel.a)

obj = ctypes.CDLL('struct_example.so')

obj.normalize.argtypes = (ctypes.POINTER(Pixel), ctypes.c_uint, ctypes.c_ubyte, ctypes.c_ubyte, ctypes.c_ubyte)

array_type = Pixel * pixels_num
obj.normalize(array_type(*pixels), pixels_num, mean, mean, mean)

print('normalized pixels:', pixels)
for pixel in pixels:
print(pixel.r, pixel.g, pixel.b, pixel.a)

我使用 gcc struct_example.c -fPIC -shared -o struct_example.so 编译 C 代码,运行 Python 代码并得到以下结果,这不是我所期望的:

original pixels: [<__main__.Pixel object at 0x7f66c17f8e18>, <__main__.Pixel object at 0x7f66c1486400>, <__main__.Pixel object at 0x7f66c1486620>]
255 255 255 0
128 128 128 0
0 128 128 0
normalized pixels: [<__main__.Pixel object at 0x7f66c17f8e18>, <__main__.Pixel object at 0x7f66c1486400>, <__main__.Pixel object at 0x7f66c1486620>]
255 255 255 0
128 128 128 0
0 128 128 0

我期望得到的是像素至少改变了。我是否错过了什么,如果我想在调用 C 算法后更改列表值,我该怎么办。提前致谢。

最佳答案

列表[Python 3.Docs]: ctypes - A foreign function library for Python .

像素在 .dll 中发生了变化(或者至少它们应该是 - 基于我的声明仅查看代码,因为我没有实际测试它),但是有一个逻辑Python 代码中的错误:

  • 从列表中创建(CTypes)数组时,(内部)元素复制而不引用,使 2 个容器完全解耦强>
    • 因此,数组是动态创建的并传递给函数,函数修改了内部的像素,但更改并未反射(reflect)在初始列表中

code00.py:

#!/usr/bin/env python3

import sys
import ctypes as ct

class Pixel(ct.Structure):
_fields_ = [
("r", ct.c_ubyte),
("g", ct.c_ubyte),
("b", ct.c_ubyte),
("a", ct.c_ubyte),
]

def __str__(self):
return "RGBa({0:d}, {1:d}, {2:d}, {3:d})".format(self.r, self.g, self.b, self.a)


def print_pixel(seq, index, header=None):
text = "Sequence {0:s} element {1:d}:\n {2:s} - {3:s}".format("({0:s})".format(header) if header else "", index, repr(seq[index]), str(seq[index]))
print(text)


def main(*argv):
pixel_list = [Pixel(255, 255, 255, 0), Pixel(128, 128, 128, 0), Pixel(0, 128, 128, 0)]
PixelArray = Pixel * len(pixel_list)
pixel_array = PixelArray(*pixel_list)
pixel_index = 0

print_pixel(pixel_list, pixel_index, "pixel_list")
print_pixel(pixel_array, pixel_index, "pixel_array")

pixel_array[pixel_index].r = pixel_array[pixel_index].g = pixel_array[pixel_index].b = 128 # Modify pixel(s) in the array

print_pixel(pixel_list, pixel_index, "pixel_list")
print_pixel(pixel_array, pixel_index, "pixel_array")

#processed_pixel_list = [pixel for pixel in pixel_array]
#print_pixel(processed_pixel_list, pixel_index, "processed_pixel_list")


if __name__ == "__main__":
print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
main(*sys.argv[1:])
print("\nDone.")

输出:

e:\Work\Dev\StackOverflow\q059485131>c:\Install\pc064\Python\Python\03.08.01\python.exe code00.py
Python 3.8.1 (tags/v3.8.1:1b293b6, Dec 18 2019, 23:11:46) [MSC v.1916 64 bit (AMD64)] 64bit on win32

Sequence (pixel_list) element 0:
<__main__.Pixel object at 0x00000150C9628140> - RGBa(255, 255, 255, 0)
Sequence (pixel_array) element 0:
<__main__.Pixel object at 0x00000150C9628540> - RGBa(255, 255, 255, 0)
Sequence (pixel_list) element 0:
<__main__.Pixel object at 0x00000150C9628140> - RGBa(255, 255, 255, 0)
Sequence (pixel_array) element 0:
<__main__.Pixel object at 0x00000150C9628540> - RGBa(128, 128, 128, 0)

Done.

正如所见,无需 .dll 即可复制该行为。要解决该问题,可以:

  • 使用数组(创建后)
  • 处理完数组后,创建一个列表(但我看不到任何好处)

关于python - 将列表从 Python 传递到 C,列表值在处理后未更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59485131/

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