我在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 intance不应该是指针而是对象本身,或类似的东西。 ==> WebKitWebFrame *框架,JSContextRef js(不是指针) 我怎样才能做到这一点。现在它只是段错误
答案 0 :(得分:1)
需要在ctypes函数上显式设置参数类型和返回类型。 ctypes使用默认返回类型“C int”,这可能是发生segfault的原因。请参阅:Specifying the required argument types
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是可以的。它在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)