5353#
5454# - Declaring C++ classes in Cython. Storing python callbacks
5555# in a C++ class using Py_INCREF, Py_DECREF. Calling from
56- # C++ using PyObject_CallMethod.
56+ # C++ using PyObject_CallMethod.
5757# | http://stackoverflow.com/a/17070382/623622
58- # Disadvantage: when calling python callback from the C++ class
58+ # Disadvantage: when calling python callback from the C++ class
5959# declared in Cython there is no easy way to propagate the python
6060# exceptions when they occur during execution of the callback.
6161#
6262# - | cdef char* other_c_string = py_string
63- # This is a very fast operation after which other_c_string points
64- # to the byte string buffer of the Python string itself. It is
65- # tied to the life time of the Python string. When the Python
63+ # This is a very fast operation after which other_c_string points
64+ # to the byte string buffer of the Python string itself. It is
65+ # tied to the life time of the Python string. When the Python
6666# string is garbage collected, the pointer becomes invalid.
6767#
6868# - Do not define cpdef functions returning "cpp_bool":
@@ -172,22 +172,20 @@ IF CEF_VERSION == 3:
172172 include " response_cef3.pyx"
173173 include " web_request_cef3.pyx"
174174
175+ # Linux issue:
176+ # ------------
175177# Try not to run any of the CEF code until Initialize() is called.
176- # Do not allocate any memory on the heap until Initialize() is called,
177- # that's why we're not instantiating the ClientHandler class here in
178- # the declaration. CEF hooks up its own tcmalloc globally when the
179- # library is loaded, but the memory allocation implementation may still
180- # be changed by another library (wx/gtk) before Initialize() is called.
181- cdef CefRefPtr[ClientHandler] g_clientHandler
178+ # Do not allocate any memory on the heap until Initialize() is called.
179+ # CEF hooks up its own tcmalloc globally when the library is loaded,
180+ # but the memory allocation implementation may still be changed by
181+ # another library (wx/gtk) before Initialize() is called.
182+ # See Issue 73:
183+ # https://code.google.com/p/cefpython/issues/detail?id=73
182184
183185def Initialize (applicationSettings = None ):
184186 Debug(" -" * 60 )
185187 Debug(" Initialize() called" )
186188
187- global g_clientHandler
188- if not g_clientHandler.get():
189- g_clientHandler = < CefRefPtr[ClientHandler]?> new ClientHandler()
190-
191189 cdef CefRefPtr[CefApp] cefApp
192190
193191 IF CEF_VERSION == 3 :
@@ -198,7 +196,9 @@ def Initialize(applicationSettings=None):
198196 ELIF UNAME_SYSNAME == " Linux" :
199197 # TODO: use the CefMainArgs(int argc, char** argv) constructor.
200198 cdef CefMainArgs cefMainArgs
201- cdef int exitCode = CefExecuteProcess(cefMainArgs, cefApp)
199+ cdef int exitCode = 1
200+ with nogil:
201+ exitCode = CefExecuteProcess(cefMainArgs, cefApp)
202202 Debug(" CefExecuteProcess(): exitCode = %s " % exitCode)
203203 if exitCode >= 0 :
204204 sys.exit(exitCode)
@@ -224,11 +224,14 @@ def Initialize(applicationSettings=None):
224224 Debug(" CefInitialize()" )
225225 cdef cpp_bool ret
226226 IF CEF_VERSION == 1 :
227- ret = CefInitialize(cefApplicationSettings, cefApp)
227+ with nogil:
228+ ret = CefInitialize(cefApplicationSettings, cefApp)
228229 ELIF CEF_VERSION == 3 :
229- ret = CefInitialize(cefMainArgs, cefApplicationSettings, cefApp)
230+ with nogil:
231+ ret = CefInitialize(cefMainArgs, cefApplicationSettings, cefApp)
230232
231- if not ret: Debug(" CefInitialize() failed" )
233+ if not ret:
234+ Debug(" CefInitialize() failed" )
232235 return ret
233236
234237def CreateBrowserSync (windowInfo , browserSettings , navigateUrl ):
@@ -251,10 +254,13 @@ def CreateBrowserSync(windowInfo, browserSettings, navigateUrl):
251254 PyToCefString(navigateUrl, cefNavigateUrl)
252255
253256 Debug(" CefBrowser::CreateBrowserSync()" )
254- global g_clientHandler
255- cdef CefRefPtr[CefBrowser] cefBrowser = cef_browser_static.CreateBrowserSync(
256- cefWindowInfo, < CefRefPtr[CefClient]?> g_clientHandler, cefNavigateUrl,
257- cefBrowserSettings)
257+ cdef CefRefPtr[ClientHandler] clientHandler = \
258+ < CefRefPtr[ClientHandler]?> new ClientHandler()
259+ cdef CefRefPtr[CefBrowser] cefBrowser
260+ with nogil:
261+ cefBrowser = cef_browser_static.CreateBrowserSync(
262+ cefWindowInfo, < CefRefPtr[CefClient]?> clientHandler,
263+ cefNavigateUrl, cefBrowserSettings)
258264
259265 if < void * > cefBrowser == NULL :
260266 Debug(" CefBrowser::CreateBrowserSync() failed" )
@@ -269,7 +275,7 @@ def CreateBrowserSync(windowInfo, browserSettings, navigateUrl):
269275 # Test whether process message sent before renderer thread is created
270276 # will be delivered - OK.
271277 # Debug("Sending 'CreateBrowserSync() done' message to the Renderer")
272- # pyBrowser.SendProcessMessage(cef_types.PID_RENDERER,
278+ # pyBrowser.SendProcessMessage(cef_types.PID_RENDERER,
273279 # "CreateBrowserSync() done")
274280
275281 return pyBrowser
@@ -299,14 +305,18 @@ def SingleMessageLoop():
299305
300306def QuitMessageLoop ():
301307 Debug(" QuitMessageLoop()" )
302- CefQuitMessageLoop()
308+ with nogil:
309+ CefQuitMessageLoop()
303310
304311def Shutdown ():
305312 Debug(" Shutdown()" )
306- CefShutdown()
313+ with nogil:
314+ CefShutdown()
307315
308316def SetOsModalLoop (py_bool modalLoop ):
309- CefSetOSModalLoop(bool (modalLoop))
317+ cdef cpp_bool cefModalLoop = bool (modalLoop)
318+ with nogil:
319+ CefSetOSModalLoop(cefModalLoop)
310320
311321cpdef py_void SetGlobalClientCallback(py_string name, object callback):
312322 global g_globalClientCallbacks
0 commit comments