2013-08-29 25 views
0

我做在python從ctype.c_void_pointer

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 * frame,JSContextRef js(不是指針) 我該怎麼做。現在它只是段錯誤

回答

1

參數類型和返回類型需要在ctypes函數上顯式設置。 ctypes使用默認的返回類型「C int」,這很可能是段錯誤發生的原因。請參閱: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是類型定義不透明結構指針,所以使用c_void_p可以作爲參數類型的工作:JavaScriptCore/API/JSBase.h

我覺得用sys.getsizeof的(對象())和FROM_ADDRESS沒問題。它在PyGObject單元測試中使用,因爲它確保代碼將在Python的調試版本(其中PyObject結構具有一些額外字段並具有不同大小)下正確運行。請參閱:git.gnome.org/browse/pygobject/tree/tests/test_everything.py?id=3.9.90#n36

作爲附註,PyGObject通過屬性暴露了一個指向底層GObject的PyCapsule指針「__gpointer__」。不幸的是,這不是很有用,因爲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)