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 是不透明结构指针的类型定义,因此使用 c_void_p 可以作为参数类型:JavaScriptCore/API/JSBase.h

我认为使用 sys.getsizeof(object()) 和 from_address 是可以的。它在 PyGObject 单元测试中使用,因为它确保代码将在 Python 的调试版本中正确运行(其中 PyObject 结构有一些额外的字段并且大小不同)。请参阅: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 回答