CTypes bringt Python zum Absturz

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
Fire Spike
User
Beiträge: 329
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Hallo Leute

Ich habe mir von StackOverflow ein Script geholt und modifiziert.
Es modifiziert den Colorchooser von Windows.

Code: Alles auswählen

import ctypes
import ctypes.wintypes as wtypes

class CHOOSECOLOR(ctypes.Structure):
    _fields_ = [
        ("lStructSize", wtypes.DWORD),
        ("hwndOwner", wtypes.HWND),
        ("hInstance", wtypes.HWND),
        ("rgbResult", wtypes.COLORREF),
        ("lpCustColors", ctypes.POINTER(wtypes.COLORREF)),
        ("Flags", wtypes.DWORD),
        ("lCustData", wtypes.LPARAM),
        ("lpfnHook", wtypes.LPARAM),
        ("lpTemplateName", ctypes.c_char_p)
    ]

class ColorChooser:
    CC_SOLIDCOLOR = 0x80
    CC_FULLOPEN = 0x02
    custom_color_array = ctypes.c_uint32 * 16
    color_chooser = ctypes.windll.Comdlg32.ChooseColorW

    def to_custom_color_array(self, custom_colors):
        custom_int_colors = self.custom_color_array()

        for i in range(16):
            custom_int_colors[i] = rgb_to_int(*custom_colors[i])

        return custom_int_colors

    def askcolor(self, custom_colors):
        struct = CHOOSECOLOR()

        ctypes.memset(ctypes.byref(struct), 0, ctypes.sizeof(struct))
        struct.lStructSize = ctypes.sizeof(struct)
        struct.Flags = self.CC_SOLIDCOLOR | self.CC_FULLOPEN
        struct.lpCustColors = self.to_custom_color_array(custom_colors)

        return rgb_to_hex(int_to_rgb(struct.rgbResult) if self.color_chooser(ctypes.byref(struct)) else None), struct.lpCustColors


def rgb_to_int(red, green, blue):
    return red + (green << 8) + (blue << 16)

def rgb_to_hex(rgb_color):
    return f"#{''.join(f'{hex(c)[2:].upper():0>2}' for c in rgb_color)}"

def int_to_rgb(int_color):
    red = int_color & 255
    green = (int_color >> 8) & 255
    blue = (int_color >> 16) & 255

    return (red, green, blue)

colors = [(250, 0, 0), (0, 250, 0), (0, 0, 250), (255, 255, 255)] * 4 # max 16 colors

chooser = ColorChooser()
print(list(chooser.askcolor(colors)[1]))
print("Hallo Welt")
Problem:
Ich möchte struct.lpCustColors in eine Liste umwandeln.
Wenn ich es einfach printe bekomme ich

Code: Alles auswählen

<ctypes.wintypes.LP_c_ulong object at 0x000002C36A410B40>
Wenn ich es mit list umwandeln will, kommt keine Fehlermeldung, aber es wird nichts geprintet (auch nicht "Hallo Welt").

Weiss jemand was das Problem ist?
Danke
Sirius3
User
Beiträge: 18051
Registriert: Sonntag 21. Oktober 2012, 17:20

lpCustColors füllst Du doch selbst mit `to_custom_color_array`, also weißt Du doch, wie Du an die Daten kommst.
Da solche Pointer keine Längeninformation haben, funktioniert `list` natürlich nicht, Slices dagegen schon.
Noch besser ist es aber, gar nicht erst mit dem Pointer zu arbeiten, sondern mit dem Rückgabewert von to_custom_color_array direkt:

Code: Alles auswählen

    def askcolor(self, custom_colors):
        custom_color_array = self.to_custom_color_array(custom_colors) 
        struct = CHOOSECOLOR()
        ctypes.memset(ctypes.byref(struct), 0, ctypes.sizeof(struct))
        struct.lStructSize = ctypes.sizeof(struct)
        struct.Flags = self.CC_SOLIDCOLOR | self.CC_FULLOPEN
        struct.lpCustColors = custom_color_array
        success = self.color_chooser(ctypes.byref(struct))
        return rgb_to_hex(int_to_rgb(struct.rgbResult)) if success else None, list(map(int_to_rgb, custom_color_array))
Fire Spike
User
Beiträge: 329
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Vielen Dank Sirius.
Es war da erste Mal, dass ich ctypes verwendete, deshalb war es schwierig für mich.
Dank deiner Erklärung verstehe ich es jetzt.
Fire Spike
User
Beiträge: 329
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Ich hätte da noch eine weitere Frage.
Wenn ich struct.rgbResult definieren will setzt sich das automatisch auf 0.

Code: Alles auswählen

        print(rgb_to_int(*hex_to_rgb(initial_color)))
        print(ctypes.c_uint32(rgb_to_int(*hex_to_rgb(initial_color))))
        struct.rbgResult = ctypes.c_uint32(rgb_to_int(*hex_to_rgb(initial_color)))
        print(struct.rgbResult)

Code: Alles auswählen

11184895
c_ulong(11184895)
0
Fire Spike
User
Beiträge: 329
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Falls euch das weiterhilft...
Ich verwende Python 3.10.4
Fire Spike
User
Beiträge: 329
Registriert: Montag 13. Mai 2019, 16:05
Wohnort: Erde

Problem hat sich gelöst.
Antworten