diff --git a/pysrc/juliacall/__init__.py b/pysrc/juliacall/__init__.py index 33991fae..2f7ff5fa 100644 --- a/pysrc/juliacall/__init__.py +++ b/pysrc/juliacall/__init__.py @@ -269,8 +269,8 @@ def jlstr(x): return 'raw"' + x + '"' script = ''' try - Base.require(Main, :CompilerSupportLibraries_jll) - global __PythonCall_libptr = Ptr{{Cvoid}}(UInt({})) + import CompilerSupportLibraries_jll as _ + global __PythonCall_embedded__ = nothing ENV["JULIA_PYTHONCALL_EXE"] = {} using PythonCall catch err @@ -280,7 +280,6 @@ def jlstr(x): rethrow() end '''.format( - hex(c.pythonapi._handle), jlstr(sys.executable or ''), ) res = jl_eval(script.encode('utf8')) diff --git a/src/C/context.jl b/src/C/context.jl index 0a1c9eb6..e8eba368 100644 --- a/src/C/context.jl +++ b/src/C/context.jl @@ -103,13 +103,43 @@ Execute `f()` on the main thread. on_main_thread +function find_lib_ptr() + # borrowed from PyCall.jl/src/startup.jl + @static if Sys.iswindows() + EnumProcessModules(hProcess, lphModule, cb, lpcbNeeded) = + ccall(:K32EnumProcessModules, stdcall, Bool, + (Ptr{Cvoid}, Ptr{Ptr{Cvoid}}, UInt32, Ptr{UInt32}), + hProcess, lphModule, cb, lpcbNeeded) + + lpcbneeded = Ref{UInt32}() + proc_handle = ccall(:GetCurrentProcess, stdcall, Ptr{Cvoid}, ()) + handles = Vector{Ptr{Cvoid}}(undef, 20) + if EnumProcessModules(proc_handle, handles, sizeof(handles), lpcbneeded) == 0 + resize!(handles, div(lpcbneeded[],sizeof(Ptr{Cvoid}))) + if EnumProcessModules(proc_handle, handles, sizeof(handles), lpcbneeded) == 0 + error() + end + end + for handle in handles + if ccall(:GetProcAddress, stdcall, Ptr{Cvoid}, + (Ptr{Cvoid}, Ptr{UInt8}), handle, "Py_GetVersion") != C_NULL + return handle + end + end + error("could not find libpython handle") + else + return unsafe_load(cglobal(:jl_exe_handle, Ptr{Cvoid})) + end +end + + function init_context() - CTX.is_embedded = hasproperty(Base.Main, :__PythonCall_libptr) + CTX.is_embedded = hasproperty(Base.Main, :__PythonCall_embedded__) if CTX.is_embedded # In this case, getting a handle to libpython is easy - CTX.lib_ptr = Base.Main.__PythonCall_libptr::Ptr{Cvoid} + CTX.lib_ptr = find_lib_ptr() init_pointers() # Check Python is initialized Py_IsInitialized() == 0 && error("Python is not already initialized.") diff --git a/src/C/pointers.jl b/src/C/pointers.jl index 9644329f..4114f0a0 100644 --- a/src/C/pointers.jl +++ b/src/C/pointers.jl @@ -282,7 +282,7 @@ end const POINTERS = CAPIPointers() -@eval init_pointers(p::CAPIPointers = POINTERS, lib::Ptr = CTX.lib_ptr) = begin +@eval function init_pointers(p::CAPIPointers = POINTERS, lib::Ptr = CTX.lib_ptr) $([ :(p.$name = dlsym(lib, $(QuoteNode(name)))) for name in CAPI_FUNCS @@ -295,6 +295,7 @@ const POINTERS = CAPIPointers() ) $([:(p.$name = dlsym(lib, $(QuoteNode(name)))) for name in CAPI_OBJECTS]...) p.PyOS_InputHookPtr = dlsym(CTX.lib_ptr, :PyOS_InputHook) + nothing end for (name, (argtypes, rettype)) in CAPI_FUNC_SIGS