1

私はPythonで次のことをやっています

import ctypes, ctypes.util
from gi.repository import WebKit, JSCore, GLib, Gtk
import sys

webkit = ctypes.CDLL(ctypes.util.find_library('webkitgtk-3.0'))
jscore = ctypes.CDLL(ctypes.util.find_library('javascriptcoregtk-3.0'))

def inject_js(view, frame):
    """
    void
    evalscript(WebKitWebFrame *frame, JSContextRef js, char *script, char* scriptname) { 
        JSStringRef jsscript, jsscriptname; 
        JSValueRef exception = NULL; 
        jsscript = JSStringCreateWithUTF8CString(script); 
        jsscriptname = JSStringCreateWithUTF8CString(scriptname); 
        JSEvaluateScript(js, jsscript, JSContextGetGlobalObject(js), jsscriptname, 0, &exception); 
        JSStringRelease(jsscript); 
        JSStringRelease(jsscriptname); 
    } 
    """

    offset = sys.getsizeof(object())
    frame = ctypes.POINTER(ctypes.c_void_p).from_address(id(frame) + offset)

    adr = webkit.webkit_web_frame_get_global_context(c_frame)
    js = ctypes.cast(js_ctx_adr, ctypes.c_void_p)

    js_objref_adr = jscore.JSContextGetGlobalObject(js_ctx_ref) #segfaults here


window = Gtk.Window()
view = WebKit.WebView()
window.add(view)
window.show_all()

view.connect('document-load-finished', inject_js)
view.load_uri("http://google.com")
mainloop = GLib.MainLoop()
mainloop.run()

ctypes を使用して内省不可能なメソッドにアクセスしようとしていますが、これまでのところ、gtk/gobject へのポインターの作成に成功しています。ただし、キャストしようとしているjsインスタンスは、ポインターではなく、オブジェクト自体または同様のものにする必要があります。==> WebKitWebFrame *frame, JSContextRef js (ポインターではない) 今のところ、セグメンテーション違反だけです

4

1 に答える 1

1

引数の型と戻り値の型は、ctypes 関数で明示的に設定する必要があります。ctypes はデフォルトの戻り値の型「C int」を使用します。これがセグメンテーション違反の原因である可能性があります。参照:必要な引数の型の指定

jscore.JSContextGetGlobalObject.argtypes = [ctypes.c_void_p]
jscore.JSContextGetGlobalObject.restype = ctypes.c_void_p

webkit.webkit_web_frame_get_global_context.argtypes = [ctypes.c_void_p]
webkit.webkit_web_frame_get_global_context.restype = ctypes.c_void_p

JSContextRef と JSGlobalContextRef は、不透明な構造体ポインターへの typedef であるため、c_void_p を使用すると、引数の型として機能できます: JavaScriptCore/API/JSBase.h

sys.getsizeof(object()) と from_address の使用は問題ないと思います。これは、Python のデバッグ ビルド (PyObject 構造体にいくつかの追加フィールドがあり、サイズが異なる) でコードが正しく実行されることを保証するため、PyGObject 単体テストで使用されます。参照: git.gnome.org/browse/pygobject/tree/tests/test_everything.py?id=3.9.90#n36

補足として、PyGObject は、属性 "__gpointer__" を介して、基になる GObject へのポインターを PyCapsule として公開します。残念ながら、ctypes は PyCapsules に保持されているポインターを自動的にマーシャリングせず、Python の PyCapsule でポインター アドレスにアクセスできないように見えるため、これはあまり役に立ちません。

前述の argtypes/restype の設定 (および変数名の修正) により、コールバックはセグメンテーション違反をしなくなりました。

def inject_js(view, frame):
    offset = sys.getsizeof(object())
    c_frame = ctypes.c_void_p.from_address(id(frame) + offset)

    js_ctx_ptr = webkit.webkit_web_frame_get_global_context(c_frame)
    js_obj_ptr = jscore.JSContextGetGlobalObject(js_ctx_ptr)
于 2013-08-29T23:58:33.480 に答える