@@ -24,6 +24,19 @@ libpython = C_NULL # Python shared library (from dlopen)
24
24
25
25
pyfunc (func:: Symbol ) = dlsym (libpython:: Ptr{Void} , func)
26
26
27
+ # Macro version of pyfunc to cache dlsym lookup (thanks to vtjnash)
28
+ macro pyfunc (func)
29
+ z = gensym (string (func))
30
+ @eval global $ z = C_NULL
31
+ quote begin
32
+ global $ z
33
+ if $ z:: Ptr{Void} == C_NULL
34
+ $ z:: Ptr{Void} = dlsym (libpython:: Ptr{Void} , $ (esc (func)))
35
+ end
36
+ $ z:: Ptr{Void}
37
+ end end
38
+ end
39
+
27
40
# Macro version of pyinitialize() to inline initialized? check
28
41
macro pyinitialize ()
29
42
:(initialized:: Bool ? nothing : pyinitialize ())
44
57
45
58
function pydecref (o:: PyObject )
46
59
if initialized:: Bool # don't decref after pyfinalize!
47
- ccall (pyfunc ( :Py_DecRef ), Void, (PyPtr,), o. o)
60
+ ccall (( @pyfunc :Py_DecRef ), Void, (PyPtr,), o. o)
48
61
end
49
62
o. o = C_NULL
50
63
o
51
64
end
52
65
53
66
function pyincref (o:: PyObject )
54
- ccall (pyfunc ( :Py_IncRef ), Void, (PyPtr,), o)
67
+ ccall (( @pyfunc :Py_IncRef ), Void, (PyPtr,), o)
55
68
o
56
69
end
57
70
58
71
pyisinstance (o:: PyObject , t:: PyObject ) =
59
- t. o != C_NULL && ccall (pyfunc ( :PyObject_IsInstance ), Cint, (PyPtr,PyPtr), o, t. o) == 1
72
+ t. o != C_NULL && ccall (( @pyfunc :PyObject_IsInstance ), Cint, (PyPtr,PyPtr), o, t. o) == 1
60
73
61
- pyisinstance (o:: PyObject , t:: Symbol ) =
62
- ccall (pyfunc ( :PyObject_IsInstance ), Cint, (PyPtr,PyPtr), o, pyfunc (t) ) == 1
74
+ pyisinstance (o:: PyObject , t:: Ptr{Void} ) =
75
+ ccall (( @pyfunc :PyObject_IsInstance ), Cint, (PyPtr,PyPtr), o, t ) == 1
63
76
64
- pyquery (q:: Symbol , o:: PyObject ) =
65
- ccall (pyfunc (q) , Cint, (PyPtr,), o) == 1
77
+ pyquery (q:: Ptr{Void} , o:: PyObject ) =
78
+ ccall (q , Cint, (PyPtr,), o) == 1
66
79
67
80
pytypeof (o:: PyObject ) = o. o == C_NULL ? throw (ArgumentError (" NULL PyObjects have no Python type" )) : pycall (PyCall. TypeType, PyObject, o)
68
81
@@ -123,12 +136,12 @@ function pyinitialize(libpy::Ptr{Void})
123
136
error (" Calling pyinitialize after pyfinalize is not supported" )
124
137
end
125
138
libpython:: Ptr{Void} = libpy == C_NULL ? ccall (:jl_load_dynamic_library , Ptr{Void}, (Ptr{Uint8},Cuint), C_NULL , 0 ) : libpy
126
- if 0 == ccall (pyfunc ( :Py_IsInitialized ), Cint, ())
139
+ if 0 == ccall (( @pyfunc :Py_IsInitialized ), Cint, ())
127
140
if ! isempty (pyprogramname:: ASCIIString )
128
- ccall (pyfunc ( :Py_SetProgramName ), Void, (Ptr{Uint8},),
141
+ ccall (( @pyfunc :Py_SetProgramName ), Void, (Ptr{Uint8},),
129
142
pyprogramname:: ASCIIString )
130
143
end
131
- ccall (pyfunc ( :Py_InitializeEx ), Void, (Cint,), 0 )
144
+ ccall (( @pyfunc :Py_InitializeEx ), Void, (Cint,), 0 )
132
145
end
133
146
initialized:: Bool = true
134
147
inspect:: PyObject = pyimport (" inspect" )
@@ -198,7 +211,7 @@ function pyfinalize()
198
211
pydecref (inspect:: PyObject )
199
212
pygc_finalize ()
200
213
gc () # collect/decref any remaining PyObjects
201
- ccall (pyfunc ( :Py_Finalize ), Void, ())
214
+ ccall (( @pyfunc :Py_Finalize ), Void, ())
202
215
dlclose (libpython:: Ptr{Void} )
203
216
libpython:: Ptr{Void} = C_NULL
204
217
initialized:: Bool = false
@@ -215,7 +228,7 @@ pyversion() = VersionNumber(convert((Int,Int,Int,String,Int),
215
228
# Conversion of Python exceptions into Julia exceptions
216
229
217
230
# call when we are throwing our own exception
218
- pyerr_clear () = ccall (pyfunc ( :PyErr_Clear ), Void, ())
231
+ pyerr_clear () = ccall (( @pyfunc :PyErr_Clear ), Void, ())
219
232
220
233
type PyError <: Exception
221
234
msg:: String
@@ -225,10 +238,10 @@ end
225
238
function pyerr_check (msg:: String , val:: Any )
226
239
# note: don't call pyinitialize here since we will
227
240
# only use this in contexts where initialization was already done
228
- e = ccall (pyfunc ( :PyErr_Occurred ), PyPtr, ())
241
+ e = ccall (( @pyfunc :PyErr_Occurred ), PyPtr, ())
229
242
if e != C_NULL
230
243
# PyErr_Occurred returns borrowed ref
231
- ccall (pyfunc ( :Py_IncRef ), Void, (PyPtr,), e)
244
+ ccall (( @pyfunc :Py_IncRef ), Void, (PyPtr,), e)
232
245
pyerr_clear ()
233
246
throw (PyError (msg, PyObject (e)))
234
247
end
238
251
pyerr_check (msg:: String ) = pyerr_check (msg, nothing )
239
252
pyerr_check () = pyerr_check (" " )
240
253
241
- # Macros for common pyerr_check("Foo", ccall(pyfunc( :Foo), ...)) pattern.
254
+ # Macros for common pyerr_check("Foo", ccall((@pyfunc :Foo), ...)) pattern.
242
255
# (The "i" variant assumes Python is initialized.)
243
256
macro pychecki (ex)
244
257
:(pyerr_check ($ (string (ex. args[1 ]. args[2 ]. args[1 ])), $ ex))
@@ -250,7 +263,7 @@ macro pycheck(ex)
250
263
end
251
264
end
252
265
253
- # Macros to check that ccall(pyfunc( :Foo), ...) returns value != bad
266
+ # Macros to check that ccall((@pyfunc :Foo), ...) returns value != bad
254
267
# (The "i" variants assume Python is initialized.)
255
268
macro pycheckvi (ex, bad)
256
269
quote
@@ -311,10 +324,10 @@ function show(io::IO, o::PyObject)
311
324
if o. o == C_NULL
312
325
print (io, " PyObject NULL" )
313
326
else
314
- s = ccall (pyfunc ( :PyObject_Repr ), PyPtr, (PyPtr,), o)
327
+ s = ccall (( @pyfunc :PyObject_Repr ), PyPtr, (PyPtr,), o)
315
328
if (s == C_NULL )
316
329
pyerr_clear ()
317
- s = ccall (pyfunc ( :PyObject_Str ), PyPtr, (PyPtr,), o)
330
+ s = ccall (( @pyfunc :PyObject_Str ), PyPtr, (PyPtr,), o)
318
331
if (s == C_NULL )
319
332
pyerr_clear ()
320
333
return print (io, " PyObject $(o. o) " )
@@ -333,7 +346,7 @@ function ref(o::PyObject, s::String)
333
346
if (o. o == C_NULL )
334
347
throw (ArgumentError (" ref of NULL PyObject" ))
335
348
end
336
- p = ccall (pyfunc ( :PyObject_GetAttrString ), PyPtr,
349
+ p = ccall (( @pyfunc :PyObject_GetAttrString ), PyPtr,
337
350
(PyPtr, Ptr{Uint8}), o, bytestring (s))
338
351
if p == C_NULL
339
352
pyerr_clear ()
@@ -348,7 +361,7 @@ function assign(o::PyObject, v, s::String)
348
361
if (o. o == C_NULL )
349
362
throw (ArgumentError (" assign of NULL PyObject" ))
350
363
end
351
- if - 1 == ccall (pyfunc ( :PyObject_SetAttrString ), Cint,
364
+ if - 1 == ccall (( @pyfunc :PyObject_SetAttrString ), Cint,
352
365
(PyPtr, Ptr{Uint8}, PyPtr), o, bytestring (s), PyObject (v))
353
366
pyerr_clear ()
354
367
throw (KeyError (s))
390
403
# ########################################################################
391
404
392
405
pyimport (name:: String ) =
393
- PyObject (@pycheckn ccall (pyfunc ( :PyImport_ImportModule ), PyPtr,
406
+ PyObject (@pycheckn ccall (( @pyfunc :PyImport_ImportModule ), PyPtr,
394
407
(Ptr{Uint8},), bytestring (name)))
395
408
396
409
pyimport (name:: Symbol ) = pyimport (string (name))
@@ -425,10 +438,10 @@ end
425
438
426
439
# look up a global variable (in module __main__)
427
440
function pybuiltin (name:: String )
428
- main = @pycheckn ccall (pyfunc ( :PyImport_AddModule ),
441
+ main = @pycheckn ccall (( @pyfunc :PyImport_AddModule ),
429
442
PyPtr, (Ptr{Uint8},),
430
443
bytestring (" __main__" ))
431
- PyObject (@pycheckni ccall (pyfunc ( :PyObject_GetAttrString ), PyPtr,
444
+ PyObject (@pycheckni ccall (( @pyfunc :PyObject_GetAttrString ), PyPtr,
432
445
(PyPtr, Ptr{Uint8}), main,
433
446
bytestring (" __builtins__" )))[bytestring (name)]
434
447
end
@@ -477,14 +490,14 @@ function pycall(o::PyObject, returntype::TypeTuple, args...)
477
490
else
478
491
kw = PyObject (C_NULL )
479
492
end
480
- arg = PyObject (@pycheckn ccall (pyfunc ( :PyTuple_New ), PyPtr, (Int,),
493
+ arg = PyObject (@pycheckn ccall (( @pyfunc :PyTuple_New ), PyPtr, (Int,),
481
494
nargs))
482
495
for i = 1 : nargs
483
- @pycheckzi ccall (pyfunc ( :PyTuple_SetItem ), Cint, (PyPtr,Int,PyPtr),
496
+ @pycheckzi ccall (( @pyfunc :PyTuple_SetItem ), Cint, (PyPtr,Int,PyPtr),
484
497
arg, i- 1 , oargs[i])
485
498
pyincref (oargs[i]) # PyTuple_SetItem steals the reference
486
499
end
487
- ret = PyObject (@pycheckni ccall (pyfunc ( :PyObject_Call ), PyPtr,
500
+ ret = PyObject (@pycheckni ccall (( @pyfunc :PyObject_Call ), PyPtr,
488
501
(PyPtr,PyPtr,PyPtr), o, arg, kw))
489
502
jret = convert (returntype, ret)
490
503
return jret
@@ -499,15 +512,15 @@ const pyeval_fname = bytestring("PyCall.jl") # filename for pyeval
499
512
# (string/symbol => value) of local variables to use in the expression
500
513
function pyeval_ (s:: String , locals:: PyDict )
501
514
sb = bytestring (s) # use temp var to prevent gc before we are done with o
502
- o = PyObject (@pycheckn ccall (pyfunc ( :Py_CompileString ), PyPtr,
515
+ o = PyObject (@pycheckn ccall (( @pyfunc :Py_CompileString ), PyPtr,
503
516
(Ptr{Uint8}, Ptr{Uint8}, Cint),
504
517
sb, pyeval_fname, Py_eval_input))
505
- main = @pycheckni ccall (pyfunc ( :PyImport_AddModule ),
518
+ main = @pycheckni ccall (( @pyfunc :PyImport_AddModule ),
506
519
PyPtr, (Ptr{Uint8},),
507
520
bytestring (" __main__" ))
508
- maindict = @pycheckni ccall (pyfunc ( :PyModule_GetDict ), PyPtr, (PyPtr,),
521
+ maindict = @pycheckni ccall (( @pyfunc :PyModule_GetDict ), PyPtr, (PyPtr,),
509
522
main)
510
- PyObject (@pycheckni ccall (pyfunc ( :PyEval_EvalCode ),
523
+ PyObject (@pycheckni ccall (( @pyfunc :PyEval_EvalCode ),
511
524
PyPtr, (PyPtr, PyPtr, PyPtr),
512
525
o, maindict, locals))
513
526
end
0 commit comments