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

将列表从Python传递到C,处理后列表值未更新,python,ctypes,Python,Ctypes,下面是示例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;

下面是示例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;
    }
}
我使用
gcc struct_示例.C-fPIC-shared-o struct_示例编译了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
原始像素:[,]
255 255 255 0
128 128 128 0
0 128 128 0
标准化像素:[,]
255 255 255 0
128 128 128 0
0 128 128 0
我希望得到的是像素至少改变了。如果我遗漏了什么,如果我想在调用C算法后更改列表值,该怎么办。提前感谢。

正在登录

像素在.dll中被更改(或者至少它们应该被更改-我的声明仅基于查看代码,因为我没有实际测试它),但是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)
  • 从列表中创建(CTypes)数组时,(内部)元素被复制而未被引用,使两个容器完全解耦
    • 因此,数组是动态创建的,并传递给函数,函数修改了内部的像素,但更改没有反映在初始列表中
代码00.py:

#/usr/bin/env蟒蛇3
导入系统
将ctypes导入为ct
类像素(ct结构):
_字段=[
(“r”,ct.c_ubyte),
(“g”,ct.c__byte),
(“b”,ct.c_ubyte),
(“a”,ct.c_ubyte),
]
定义(自我):
返回“RGBa({0:d},{1:d},{2:d},{3:d})”格式(self.r,self.g,self.b,self.a)
def打印像素(顺序、索引、标题=无):
text=“Sequence{0:s}元素{1:d}:\n{2:s}-{3:s}”.format(({0:s})”.format(header)if header else“”,index,repr(seq[index]),str seq[index]))
打印(文本)
def主(*argv):
像素列表=[像素(255,255,255,0),像素(128,128,128,0),像素(0,128,128,0)]
像素阵列=像素*透镜(像素列表)
像素数组=像素数组(*像素数组列表)
像素指数=0
打印像素(像素列表、像素索引、“像素列表”)
打印像素(像素阵列、像素索引、“像素阵列”)
pixel_数组[pixel_index]。r=pixel_数组[pixel_index]。g=pixel_数组[pixel_index]。b=128#修改数组中的像素
打印像素(像素列表、像素索引、“像素列表”)
打印像素(像素阵列、像素索引、“像素阵列”)
#已处理的像素列表=[像素阵列中像素对像素]
#打印像素(已处理像素列表、像素索引、“已处理像素列表”)
如果名称=“\uuuuu main\uuuuuuuu”:
打印(“Python{0:s}{1:d}位在{2:s}\n.format(“.join(sys.version.split(“\n”)中的项的item.strip()),如果sys.maxsize>0x100000000,则为64,否则为32,sys.platform))
main(*sys.argv[1:])
打印(“\n完成”)
输出

e:\Work\Dev\StackOverflow\q059485131>c:\Install\pc064\Python\Python\03.08.01\Python.exe code00.py
win32上的Python 3.8.1(tags/v3.8.1:1b293b6,2019年12月18日,23:11:46)[MSC v.1916 64位(AMD64)]64位
序列(像素列表)元素0:
-RGBa(255、255、255、0)
序列(像素数组)元素0:
-RGBa(255、255、255、0)
序列(像素列表)元素0:
-RGBa(255、255、255、0)
序列(像素数组)元素0:
-RGBa(128、128、128、0)
完成。
如图所示,可以在没有.dll的情况下复制该行为。要解决此问题,请执行以下操作之一:

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

像素在.dll中被更改(或者至少它们应该被更改-我的声明仅基于查看代码,因为我没有实际测试它),但是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)
  • 从列表中创建(CTypes)数组时,(内部)元素被复制而未被引用,使两个容器完全解耦
    • 因此,数组是动态创建的,并传递给函数,函数修改了内部的像素,但更改没有反映在初始列表中
代码00.py:

#/usr/bin/env蟒蛇3
导入系统
将ctypes导入为ct
类像素(ct结构):
_字段=[
(“r”,ct.c_ubyte),
(“g”,ct.c__byte),
(“b”,ct.c_ubyte),
(“a”,ct.c_ubyte),
]
定义(自我):
返回“RGBa({0:d},{1:d},{2:d},{3:d})”格式(self.r,self.g,self.b,self.a)
def打印像素(顺序、索引、标题=无):
text=“Sequence{0:s}元素{1:d}:\n{2:s}-{3:s}”.format(({0:s})”.format(header)if header else“”,index,repr(seq[index]),str seq[index]))
打印(文本)
def主(*argv):
像素列表=[像素(255,255,255,0),像素(128,128,128,0),像素(0,128,128,0)]
像素阵列=像素*透镜(像素列表)
像素数组=像素数组(*像素数组列表)
像素指数=0
打印像素(像素列表、像素索引、“像素列表”)
打印像素(像素阵列、像素索引、“像素阵列”)
pixel_数组[pixel_index]。r=pixel_数组[pixel_index]。g=pixel_数组[pixel_index]。b=128#修改数组中的像素
打印像素(像素列表、像素索引、“像素列表”)
打印像素(像素阵列、像素索引、“像素阵列”)
#已处理的像素列表=[像素阵列中像素对像素]
#打印像素(已处理像素列表、像素索引、“已处理像素列表”)
如果名称=“\uuuuu main\uuuuuuuu”:
打印(“Python{0:s}{1:d}位在{2:s}\n.format(“.join(sys.version.split(“\n”)中的项的item.strip()),如果sys.maxsize>0x100000000,则为64,否则为32,sys.platform))
main(*sys.argv[1:])
打印(“\n完成”)
输出

e:\Work\Dev\StackOverflow\q059485131>c:\Install\pc064\Python\Python\03.08.01\Python.exe code00.py
win32上的Python 3.8.1(tags/v3.8.1:1b293b6,2019年12月18日,23:11:46)[MSC v.1916 64位(AMD64)]64位
序列(像素列表)元素0:
-RGBa(255、255、255、0)
序列(像素数组)元素0:
-RGBa(255、255、255、0)
序列(像素列表)元素0:
-RGBa