ctypes: Fremden Typ als Argument nutzen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
snafu
User
Beiträge: 6736
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@ rayo:

Nein, immer noch das selbe:

Code: Alles auswählen

Traceback (most recent call last):
  File "./test.py", line 16, in <module>
    gtk_init(byref(argc), byref(argv))
ctypes.ArgumentError: argument 2: <type 'exceptions.TypeError'>: expected LP_LP_c_char_p instance instead of pointer to c_char_p_Array_1
Übrigens muss man natürlich oben aufpassen, dass man einmal die von Python ermittelte Länge der `sys.argv`-Liste nimmt, um die Größe des Arrays mittels Multiplikation festzulegen und erst danach das `c_int`-Objekt für die Übergabe als Funktionsparameter für C. ;)
BlackJack

@snafu: Einen Typ Array gibt's indirekt über das Multiplizieren von Typen mit einer Zahl, aber Zeiger und Array sind ja in C fast das gleiche. Genau wie in C kannst Du mit `ctypes`-Zeigern auch Indexzugriffe machen. Bei `gtk_init()` sehe ich in der Signatur aber auch kein Array, sondern einen Zeiger auf einen Zeiger auf einen Zeiger auf `char`. Zeiger auf `char` gibt's schon als `c_char_p`, also müssen nur noch zwei der Sternchen durch `POINTER()` ersetzt werden.

Anscheinend ist `ctypes` da "typsicherer" als C, also bleibt nur `cast()`\en.
Benutzeravatar
snafu
User
Beiträge: 6736
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Juchhu.

Code: Alles auswählen

#!/usr/bin/env python

from ctypes import byref, cast, c_char_p, CDLL, c_int, POINTER
from ctypes.util import find_library
import sys


def gtk_init(argv=sys.argv):
    assert isinstance(argv, list)
    args_no = len(argv)
    argc = c_int(args_no)
    argv = cast((c_char_p * args_no)(*argv), POINTER(c_char_p))

    gtk = CDLL(find_library('gtk-x11-2.0'))
    gtk_init = gtk.gtk_init
    gtk_init.argtypes = [POINTER(c_int), POINTER(POINTER(c_char_p))]
    return gtk_init(byref(argc), byref(argv)) == 1


if __name__ == '__main__':
    print gtk_init()
`ctypes` und ich werden, glaube ich, noch gute Freunde. :)
Benutzeravatar
snafu
User
Beiträge: 6736
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Hier mal ein Beispiel für ein `web_view` in einem Fenster. Mit dem Herumreichen von Variablen sozusagen innerhalb des C-Kontextes habe ich also kein Problem.

Schwierig wird allerdings das testweise Auslesen der URL aus meinem `network_request`. Signatur:

Code: Alles auswählen

const gchar *       webkit_network_request_get_uri      (WebKitNetworkRequest *request);
In meinem Ansatz sage ich einfach, dass die Rückgabe von Typ `c_char_p` ist, aber das reicht offenbar nicht. Ich bekomme nur irgendwelche komischen Zeichen zurück. :(
BlackJack

Was hättest Du denn jetzt da erwartet? Woher soll da auf magische Weise eine URI kommen?
Benutzeravatar
snafu
User
Beiträge: 6736
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Huch, danke. Die URL muss natürlich erst noch gesetzt werden. :oops:

Code: Alles auswählen

[...]
if __name__ == '__main__':
    init_gtk()
    request = webkit.webkit_network_request_new()
    
    url = 'http://www.google.de/'
    webkit.webkit_network_request_set_uri(request, url)
    
    get_uri = webkit.webkit_network_request_get_uri
    get_uri.restype = c_char_p
    print get_uri(request)
Antworten