@@ -589,4 +589,184 @@ end
589589# Convenient parsing for argv (slight type piracy)
590590@inline Base. parse (:: Type{T} , argv:: Ptr{Ptr{UInt8}} , n:: Integer ) where {T} = parse (T, MallocString (argv, n))
591591
592+ # # --- dlopen
593+
594+ const RTLD_LOCAL = Int32 (1 )
595+ const RTLD_GLOBAL = Int32 (2 )
596+ const RTLD_LAZY = Int32 (4 )
597+ const RTLD_NOW = Int32 (8 )
598+
599+ """
600+ ```julia
601+ dlopen(name::AbstractString, flag=RTLD_LOCAL|RTLD_LAZY)
602+ ```
603+ Libc `dlopen` function, accessed by direct `llvmcall`.
604+
605+ Returns a handle (pointer) to a `.so`/`.dylib` shared library specified by
606+ `name` opened with the mode or combination of modes specified by `flag`.
607+ Returns `C_NULL` on failure. Valid modes include:
608+
609+ Required:
610+
611+ `RTLD_LOCAL` (default): Symbols will not be made available for subsequently loaded libraries. The opposite of `RTLD_GLOBAL`.
612+
613+ `RTLD_GLOBAL`: Symbols will be made available for subsequently loaded libraries. The opposite of `RTLD_LOCAL`.
614+
615+ Optional:
616+
617+ `RTLD_LAZY` (default): Lazy binding: only resolve symbols as the code that references them is executed. The opposite of `RLTD_NOW`.
618+
619+ `RTLD_NOW`: Eager binding: resolve all symbols before `dlopen` returns. The opposite of `RTLD_LAZY`
620+
621+ Modes from the two categories can be combined with bitwise `or` (`|`)
622+
623+ See also: `StaticTools.dlsym`, `StaticTools.@ptrcall`, `StaticTools.dlclose`
624+
625+ ## Examples
626+ ```julia
627+ julia> lib = StaticTools.dlopen(c"libc.dylib") # on macOS
628+ Ptr{StaticTools.DYLIB} @0x000000010bf49b78
629+
630+ julia> fp = StaticTools.dlsym(lib, c"time")
631+ Ptr{Nothing} @0x00007fffa773dfa4
632+
633+ julia> dltime() = @ptrcall fp()::Int
634+ ctime (generic function with 1 method)
635+
636+ julia> dltime()
637+ 1654320146
638+
639+ julia> StaticTools.dlclose(lib)
640+ 0
641+ ```
642+ """
643+ @inline dlopen (name:: AbstractMallocdMemory , flag= RTLD_LOCAL| RTLD_LAZY) = dlopen (pointer (name), flag)
644+ @inline dlopen (name, flag= RTLD_LOCAL| RTLD_LAZY) = GC. @preserve name dlopen (pointer (name), flag)
645+ @inline function dlopen (name:: Ptr{UInt8} , flag:: Int32 )
646+ Base. llvmcall (("""
647+ ; External declaration of the dlopen function
648+ declare i8* @dlopen(i8*, i32)
649+
650+ define i64 @main(i64 %jlname, i32 %flag) #0 {
651+ entry:
652+ %name = inttoptr i64 %jlname to i8*
653+ %fp = call i8* (i8*, i32) @dlopen(i8* %name, i32 %flag)
654+ %jlfp = ptrtoint i8* %fp to i64
655+ ret i64 %jlfp
656+ }
657+
658+ attributes #0 = { alwaysinline nounwind ssp uwtable }
659+ """ , " main" ), Ptr{DYLIB}, Tuple{Ptr{UInt8}, Int32}, name, flag)
660+ end
661+
662+ @static if Sys. isapple ()
663+ const DLEXT = c " .dylib"
664+ elseif Sys. iswindows ()
665+ const DLEXT = c " .dll"
666+ else
667+ const DLEXT = c " .so"
668+ end
669+
670+ # # --- dylsym
671+
672+ """
673+ ```julia
674+ dlsym(lib::Ptr{DYLIB}, symbol::AbstractString)
675+ ```
676+ Libc `dlsym` function, accessed by direct StaticCompiler-safe `llvmcall`.
677+
678+ Takes a handle (`lib`) to a `.so`/`.dylib` shared library previously opened with
679+ `StaticTools.dlopen`, along with a null-terminated symbol name string (`symbol`),
680+ and returns the location in memory of that symbol. Returns `C_NULL` on failure.
681+
682+ See also: `StaticTools.dlopen`, `StaticTools.@ptrcall`, `StaticTools.dlclose`
683+
684+ ## Examples
685+ ```julia
686+ julia> lib = StaticTools.dlopen(c"libc.dylib") # on macOS
687+ Ptr{StaticTools.DYLIB} @0x000000010bf49b78
688+
689+ julia> fp = StaticTools.dlsym(lib, c"time")
690+ Ptr{Nothing} @0x00007fffa773dfa4
691+
692+ julia> dltime() = @ptrcall fp()::Int
693+ dltime (generic function with 1 method)
694+
695+ julia> dltime()
696+ 1654320146
697+
698+ julia> StaticTools.dlclose(lib)
699+ 0
700+ ```
701+ """
702+ @inline dlsym (handle:: Ptr{DYLIB} , symbol:: AbstractMallocdMemory ) = dlsym (handle, pointer (symbol))
703+ @inline dlsym (handle:: Ptr{DYLIB} , symbol) = GC. @preserve symbol dlsym (handle, pointer (symbol))
704+ @inline function dlsym (handle:: Ptr{DYLIB} , symbol:: Ptr{UInt8} )
705+ Base. llvmcall (("""
706+ ; External declaration of the dlsym function
707+ declare i8* @dlsym(i8*, i8*)
708+
709+ define i64 @main(i64 %jlh, i64 %jls) #0 {
710+ entry:
711+ %handle = inttoptr i64 %jlh to i8*
712+ %symbol = inttoptr i64 %jls to i8*
713+ %fp = call i8* (i8*, i8*) @dlsym(i8* %handle, i8* %symbol)
714+ %jlfp = ptrtoint i8* %fp to i64
715+ ret i64 %jlfp
716+ }
717+
718+ attributes #0 = { alwaysinline nounwind ssp uwtable }
719+ """ , " main" ), Ptr{Nothing}, Tuple{Ptr{DYLIB}, Ptr{UInt8}}, handle, symbol)
720+ end
721+
722+ # Return default handle to what Julia has already dlopened, for interactive use
723+ jl_RTLD_DEFAULT_handle () = @externload jl_RTLD_DEFAULT_handle:: Ptr{DYLIB}
724+
725+ # # --- dlclose
726+
727+ """
728+ ```julia
729+ dlclose(lib::Ptr{DYLIB})
730+ ```
731+ Libc `dlclose` function, accessed by direct StaticCompiler-safe `llvmcall`.
732+
733+ Close a shared library `lib` given a pointer (handle) previously obtained from
734+ `StaticTools.dlopen`.
735+
736+ See also: `StaticTools.dlopen`, `StaticTools.dlsym`, `StaticTools.@ptrcall`
737+
738+ ## Examples
739+ ```julia
740+ julia> lib = StaticTools.dlopen(c"libc.dylib") # on macOS
741+ Ptr{StaticTools.DYLIB} @0x000000010bf49b78
742+
743+ julia> fp = StaticTools.dlsym(lib, c"time")
744+ Ptr{Nothing} @0x00007fffa773dfa4
745+
746+ julia> dltime() = @ptrcall fp()::Int
747+ dltime (generic function with 1 method)
748+
749+ julia> dltime()
750+ 1654320146
751+
752+ julia> StaticTools.dlclose(lib)
753+ 0
754+ ```
755+ """
756+ @inline function dlclose (handle:: Ptr{DYLIB} )
757+ Base. llvmcall (("""
758+ ; External declaration of the dlclose function
759+ declare i32 @dlclose(i8*)
760+
761+ define i32 @main(i64 %jlh) #0 {
762+ entry:
763+ %handle = inttoptr i64 %jlh to i8*
764+ %status = call i32 (i8*) @dlclose(i8* %handle)
765+ ret i32 %status
766+ }
767+
768+ attributes #0 = { alwaysinline nounwind ssp uwtable }
769+ """ , " main" ), Int32, Tuple{Ptr{DYLIB}}, handle)
770+ end
771+
592772# # ---
0 commit comments