Skip to content

Instantly share code, notes, and snippets.

@thautwarm
Last active August 7, 2020 04:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thautwarm/35db339531f3ff9efd5128de2bc9362f to your computer and use it in GitHub Desktop.
Save thautwarm/35db339531f3ff9efd5128de2bc9362f to your computer and use it in GitHub Desktop.
using MLStyle
using Libdl
struct DLL
path :: String
handle::Ptr{Nothing}
end
function DLL(path::String)
handle = dlopen_e(path)
if handle === C_NULL
error("dynlib $path not found")
end
DLL(path, handle)
end
macro external(dll, ex)
retex = @when :($fname($(args...))::$ret_ty) = ex begin
anns = []
types = []
params = []
for i in eachindex(args)
arg = args[i]
@switch arg begin
@case :(::$ty)
param = Symbol("__", i)
push!(anns, :($param :: $ty))
push!(types, ty)
push!(params, param)
continue
@case :($(param::Symbol)::$ty)
push!(anns, :($param :: $ty))
push!(types, ty)
push!(params, param)
continue
@case _
error("malformed arg $arg")
end
end
argtype = Expr(:tuple, types...)
Expr(
:let,
:(external_func = $dlsym_e($dll.handle, $fname)),
Expr(
:block,
Expr(
:function,
Expr(:call, fname, anns...),
Expr(
:block,
:(ccall(external_func, $ret_ty, $argtype, $(params...)))
)
)
)
)
@when :($(var::Symbol)::Ptr{$ty}) = ex
:(cglobal(($(QuoteNode(var)), $dll.path), Ptr{$ty}))
@otherwise
error("expect 'var::Ptr{Type}' or 'f(arg::Type, ...)::Type', got $ex")
end
esc(retex)
end
dll = DLL("libpython3.8")
Py_Initialize = @external dll Py_Initialize()::Cvoid
Py_IsInitialized = @external dll Py_IsInitialized()::Cint
Py_Initialize()
Py_IsInitialized() # => 1
PyExc_ImportError = @external dll PyExc_ImportError::Ptr{Cvoid}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment