Here is the sample C code:
#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;
}
}
and the Python code:
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)
I compile the C code with gcc struct_example.c -fPIC -shared -o struct_example.so
, run the Python code and get the following result which is not what I expected:
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
What I expected to get is the pixels are changed at least. Did I missed something, what should I do if I want the list value changed after calling to C algorithms. Thanks in advance.
Listing [Python 3.Docs]: ctypes - A foreign function library for Python .
The pixels are changed in the .dll (or at least they should be - basing my statement on looking at the code only, as I didn't actually test it), but there's a logical error in the Python code:
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.")
Output :
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.
As seen, it's possible to replicate the behavior without a .dll . To go around the problem, either:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.