"Fossies" - the Fresh Open Source Software Archive

Member "julia-1.1.1/share/julia/base/c.jl" (16 May 2019, 16731 Bytes) of package /linux/misc/julia-1.1.1-linux-i686.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Julia source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 # This file is a part of Julia. License is MIT: https://julialang.org/license
    2 
    3 # definitions related to C interface
    4 
    5 import Core.Intrinsics: cglobal, bitcast
    6 
    7 """
    8     cglobal((symbol, library) [, type=Cvoid])
    9 
   10 Obtain a pointer to a global variable in a C-exported shared library, specified exactly as
   11 in [`ccall`](@ref).
   12 Returns a `Ptr{Type}`, defaulting to `Ptr{Cvoid}` if no `Type` argument is
   13 supplied.
   14 The values can be read or written by [`unsafe_load`](@ref) or [`unsafe_store!`](@ref),
   15 respectively.
   16 """
   17 cglobal
   18 
   19 """
   20     CFunction struct
   21 
   22 Garbage-collection handle for the return value from `@cfunction`
   23 when the first argument is annotated with '\\\$'.
   24 Like all `cfunction` handles, it should be passed to `ccall` as a `Ptr{Cvoid}`,
   25 and will be converted automatically at the call site to the appropriate type.
   26 
   27 See [`@cfunction`](@ref).
   28 """
   29 struct CFunction <: Ref{Cvoid}
   30     ptr::Ptr{Cvoid}
   31     f::Any
   32     _1::Ptr{Cvoid}
   33     _2::Ptr{Cvoid}
   34     let constructor = false end
   35 end
   36 unsafe_convert(::Type{Ptr{Cvoid}}, cf::CFunction) = cf.ptr
   37 
   38 """
   39     @cfunction(callable, ReturnType, (ArgumentTypes...,)) -> Ptr{Cvoid}
   40     @cfunction(\$callable, ReturnType, (ArgumentTypes...,)) -> CFunction
   41 
   42 Generate a C-callable function pointer from the Julia function `closure`
   43 for the given type signature.
   44 To pass the return value to a `ccall`, use the argument type `Ptr{Cvoid}` in the signature.
   45 
   46 Note that the argument type tuple must be a literal tuple, and not a tuple-valued variable or expression
   47 (although it can include a splat expression). And that these arguments will be evaluated in global scope
   48 during compile-time (not deferred until runtime).
   49 Adding a '\\\$' in front of the function argument changes this to instead create a runtime closure
   50 over the local variable `callable`.
   51 
   52 See [manual section on ccall and cfunction usage](@ref Calling-C-and-Fortran-Code).
   53 
   54 # Examples
   55 ```julia-repl
   56 julia> function foo(x::Int, y::Int)
   57            return x + y
   58        end
   59 
   60 julia> @cfunction(foo, Int, (Int, Int))
   61 Ptr{Cvoid} @0x000000001b82fcd0
   62 ```
   63 """
   64 macro cfunction(f, at, rt)
   65     if !(isa(rt, Expr) && rt.head === :tuple)
   66         throw(ArgumentError("@cfunction argument types must be a literal tuple"))
   67     end
   68     rt.head = :call
   69     pushfirst!(rt.args, GlobalRef(Core, :svec))
   70     if isa(f, Expr) && f.head === :$
   71         fptr = f.args[1]
   72         typ = CFunction
   73     else
   74         fptr = QuoteNode(f)
   75         typ = Ptr{Cvoid}
   76     end
   77     cfun = Expr(:cfunction, typ, fptr, at, rt, QuoteNode(:ccall))
   78     return esc(cfun)
   79 end
   80 
   81 if ccall(:jl_is_char_signed, Ref{Bool}, ())
   82     const Cchar = Int8
   83 else
   84     const Cchar = UInt8
   85 end
   86 """
   87     Cchar
   88 
   89 Equivalent to the native `char` c-type.
   90 """
   91 Cchar
   92 
   93 # The ccall here is equivalent to Sys.iswindows(), but that's not defined yet
   94 @static if ccall(:jl_get_UNAME, Any, ()) === :NT
   95     const Clong = Int32
   96     const Culong = UInt32
   97     const Cwchar_t = UInt16
   98 else
   99     const Clong = Int
  100     const Culong = UInt
  101     const Cwchar_t = Int32
  102 end
  103 
  104 """
  105     Clong
  106 
  107 Equivalent to the native `signed long` c-type.
  108 """
  109 Clong
  110 
  111 """
  112     Culong
  113 
  114 Equivalent to the native `unsigned long` c-type.
  115 """
  116 Culong
  117 
  118 """
  119     Cwchar_t
  120 
  121 Equivalent to the native `wchar_t` c-type ([`Int32`](@ref)).
  122 """
  123 Cwchar_t
  124 
  125 """
  126     Cwstring
  127 
  128 A C-style string composed of the native wide character type
  129 [`Cwchar_t`](@ref)s. `Cwstring`s are NUL-terminated. For
  130 C-style strings composed of the native character
  131 type, see [`Cstring`](@ref). For more information
  132 about string interopability with C, see the
  133 [manual](@ref man-bits-types).
  134 
  135 """
  136 Cwstring
  137 
  138 """
  139     Cstring
  140 
  141 A C-style string composed of the native character type
  142 [`Cchar`](@ref)s. `Cstring`s are NUL-terminated. For
  143 C-style strings composed of the native wide character
  144 type, see [`Cwstring`](@ref). For more information
  145 about string interopability with C, see the
  146 [manual](@ref man-bits-types).
  147 """
  148 Cstring
  149 
  150 @static if ccall(:jl_get_UNAME, Any, ()) !== :NT
  151     const sizeof_mode_t = ccall(:jl_sizeof_mode_t, Cint, ())
  152     if sizeof_mode_t == 2
  153         const Cmode_t = Int16
  154     elseif sizeof_mode_t == 4
  155         const Cmode_t = Int32
  156     elseif sizeof_mode_t == 8
  157         const Cmode_t = Int64
  158     end
  159 end
  160 
  161 # construction from pointers
  162 Cstring(p::Union{Ptr{Int8},Ptr{UInt8},Ptr{Cvoid}}) = bitcast(Cstring, p)
  163 Cwstring(p::Union{Ptr{Cwchar_t},Ptr{Cvoid}})       = bitcast(Cwstring, p)
  164 (::Type{Ptr{T}})(p::Cstring) where {T<:Union{Int8,UInt8,Cvoid}} = bitcast(Ptr{T}, p)
  165 (::Type{Ptr{T}})(p::Cwstring) where {T<:Union{Cwchar_t,Cvoid}}  = bitcast(Ptr{Cwchar_t}, p)
  166 
  167 convert(::Type{Cstring}, p::Union{Ptr{Int8},Ptr{UInt8},Ptr{Cvoid}}) = Cstring(p)
  168 convert(::Type{Cwstring}, p::Union{Ptr{Cwchar_t},Ptr{Cvoid}}) = Cwstring(p)
  169 convert(::Type{Ptr{T}}, p::Cstring) where {T<:Union{Int8,UInt8,Cvoid}} = Ptr{T}(p)
  170 convert(::Type{Ptr{T}}, p::Cwstring) where {T<:Union{Cwchar_t,Cvoid}} = Ptr{T}(p)
  171 
  172 """
  173     pointer(array [, index])
  174 
  175 Get the native address of an array or string, optionally at a given location `index`.
  176 
  177 This function is "unsafe". Be careful to ensure that a Julia reference to
  178 `array` exists as long as this pointer will be used. The [`GC.@preserve`](@ref)
  179 macro should be used to protect the `array` argument from garbage collection
  180 within a given block of code.
  181 
  182 Calling [`Ref(array[, index])`](@ref Ref) is generally preferable to this function as it guarantees validity.
  183 """
  184 function pointer end
  185 
  186 pointer(p::Cstring) = convert(Ptr{UInt8}, p)
  187 pointer(p::Cwstring) = convert(Ptr{Cwchar_t}, p)
  188 
  189 # comparisons against pointers (mainly to support `cstr==C_NULL`)
  190 ==(x::Union{Cstring,Cwstring}, y::Ptr) = pointer(x) == y
  191 ==(x::Ptr, y::Union{Cstring,Cwstring}) = x == pointer(y)
  192 
  193 unsafe_string(s::Cstring) = unsafe_string(convert(Ptr{UInt8}, s))
  194 
  195 # convert strings to String etc. to pass as pointers
  196 cconvert(::Type{Cstring}, s::String) = s
  197 cconvert(::Type{Cstring}, s::AbstractString) =
  198     cconvert(Cstring, String(s)::String)
  199 
  200 function cconvert(::Type{Cwstring}, s::AbstractString)
  201     v = transcode(Cwchar_t, String(s))
  202     !isempty(v) && v[end] == 0 || push!(v, 0)
  203     return v
  204 end
  205 
  206 eltype(::Type{Cstring}) = UInt8
  207 eltype(::Type{Cwstring}) = Cwchar_t
  208 
  209 containsnul(p::Ptr, len) =
  210     C_NULL != ccall(:memchr, Ptr{Cchar}, (Ptr{Cchar}, Cint, Csize_t), p, 0, len)
  211 containsnul(s::String) = containsnul(unsafe_convert(Ptr{Cchar}, s), sizeof(s))
  212 containsnul(s::AbstractString) = '\0' in s
  213 
  214 function unsafe_convert(::Type{Cstring}, s::Union{String,AbstractVector{UInt8}})
  215     p = unsafe_convert(Ptr{Cchar}, s)
  216     containsnul(p, sizeof(s)) &&
  217         throw(ArgumentError("embedded NULs are not allowed in C strings: $(repr(s))"))
  218     return Cstring(p)
  219 end
  220 
  221 function unsafe_convert(::Type{Cwstring}, v::Vector{Cwchar_t})
  222     for i = 1:length(v)-1
  223         v[i] == 0 &&
  224             throw(ArgumentError("embedded NULs are not allowed in C strings: $(repr(v))"))
  225     end
  226     v[end] == 0 ||
  227         throw(ArgumentError("C string data must be NUL terminated: $(repr(v))"))
  228     p = unsafe_convert(Ptr{Cwchar_t}, v)
  229     return Cwstring(p)
  230 end
  231 
  232 # symbols are guaranteed not to contain embedded NUL
  233 cconvert(::Type{Cstring}, s::Symbol) = s
  234 unsafe_convert(::Type{Cstring}, s::Symbol) = Cstring(unsafe_convert(Ptr{Cchar}, s))
  235 
  236 @static if ccall(:jl_get_UNAME, Any, ()) === :NT
  237 """
  238     Base.cwstring(s)
  239 
  240 Converts a string `s` to a NUL-terminated `Vector{Cwchar_t}`, suitable for passing to C
  241 functions expecting a `Ptr{Cwchar_t}`. The main advantage of using this over the implicit
  242 conversion provided by [`Cwstring`](@ref) is if the function is called multiple times with the
  243 same argument.
  244 
  245 This is only available on Windows.
  246 """
  247 function cwstring(s::AbstractString)
  248     bytes = codeunits(String(s))
  249     0 in bytes && throw(ArgumentError("embedded NULs are not allowed in C strings: $(repr(s))"))
  250     return push!(transcode(UInt16, bytes), 0)
  251 end
  252 end
  253 
  254 # transcoding between data in UTF-8 and UTF-16 for Windows APIs,
  255 # and also UTF-32 for APIs using Cwchar_t on other platforms.
  256 
  257 """
  258     transcode(T, src)
  259 
  260 Convert string data between Unicode encodings. `src` is either a
  261 `String` or a `Vector{UIntXX}` of UTF-XX code units, where
  262 `XX` is 8, 16, or 32. `T` indicates the encoding of the return value:
  263 `String` to return a (UTF-8 encoded) `String` or `UIntXX`
  264 to return a `Vector{UIntXX}` of UTF-`XX` data. (The alias [`Cwchar_t`](@ref)
  265 can also be used as the integer type, for converting `wchar_t*` strings
  266 used by external C libraries.)
  267 
  268 The `transcode` function succeeds as long as the input data can be
  269 reasonably represented in the target encoding; it always succeeds for
  270 conversions between UTF-XX encodings, even for invalid Unicode data.
  271 
  272 Only conversion to/from UTF-8 is currently supported.
  273 """
  274 function transcode end
  275 
  276 transcode(::Type{T}, src::AbstractVector{T}) where {T<:Union{UInt8,UInt16,UInt32,Int32}} = src
  277 transcode(::Type{T}, src::String) where {T<:Union{Int32,UInt32}} = T[T(c) for c in src]
  278 transcode(::Type{T}, src::AbstractVector{UInt8}) where {T<:Union{Int32,UInt32}} =
  279     transcode(T, String(Vector(src)))
  280 transcode(::Type{T}, src::CodeUnits{UInt8,String}) where {T<:Union{Int32,UInt32}} =
  281     transcode(T, String(src))
  282 
  283 function transcode(::Type{UInt8}, src::Vector{<:Union{Int32,UInt32}})
  284     buf = IOBuffer()
  285     for c in src
  286         print(buf, Char(c))
  287     end
  288     take!(buf)
  289 end
  290 transcode(::Type{String}, src::String) = src
  291 transcode(T, src::String) = transcode(T, codeunits(src))
  292 transcode(::Type{String}, src) = String(transcode(UInt8, src))
  293 
  294 function transcode(::Type{UInt16}, src::AbstractVector{UInt8})
  295     @assert !has_offset_axes(src)
  296     dst = UInt16[]
  297     i, n = 1, length(src)
  298     n > 0 || return dst
  299     sizehint!(dst, 2n)
  300     a = src[1]
  301     while true
  302         if i < n && -64 <= a % Int8 <= -12 # multi-byte character
  303             b = src[i += 1]
  304             if -64 <= (b % Int8) || a == 0xf4 && 0x8f < b
  305                 # invalid UTF-8 (non-continuation or too-high code point)
  306                 push!(dst, a)
  307                 a = b; continue
  308             elseif a < 0xe0 # 2-byte UTF-8
  309                 push!(dst, xor(0x3080, UInt16(a) << 6, b))
  310             elseif i < n # 3/4-byte character
  311                 c = src[i += 1]
  312                 if -64 <= (c % Int8) # invalid UTF-8 (non-continuation)
  313                     push!(dst, a, b)
  314                     a = c; continue
  315                 elseif a < 0xf0 # 3-byte UTF-8
  316                     push!(dst, xor(0x2080, UInt16(a) << 12, UInt16(b) << 6, c))
  317                 elseif i < n
  318                     d = src[i += 1]
  319                     if -64 <= (d % Int8) # invalid UTF-8 (non-continuation)
  320                         push!(dst, a, b, c)
  321                         a = d; continue
  322                     elseif a == 0xf0 && b < 0x90 # overlong encoding
  323                         push!(dst, xor(0x2080, UInt16(b) << 12, UInt16(c) << 6, d))
  324                     else # 4-byte UTF-8
  325                         push!(dst, 0xe5b8 + (UInt16(a) << 8) + (UInt16(b) << 2) + (c >> 4),
  326                                    xor(0xdc80, UInt16(c & 0xf) << 6, d))
  327                     end
  328                 else # too short
  329                     push!(dst, a, b, c)
  330                     break
  331                 end
  332             else # too short
  333                 push!(dst, a, b)
  334                 break
  335             end
  336         else # ASCII or invalid UTF-8 (continuation byte or too-high code point)
  337             push!(dst, a)
  338         end
  339         i < n || break
  340         a = src[i += 1]
  341     end
  342     return dst
  343 end
  344 
  345 function transcode(::Type{UInt8}, src::AbstractVector{UInt16})
  346     @assert !has_offset_axes(src)
  347     n = length(src)
  348     n == 0 && return UInt8[]
  349 
  350     # Precompute m = sizeof(dst).   This involves annoying duplication
  351     # of the loop over the src array.   However, this is not just an
  352     # optimization: it is problematic for security reasons to grow
  353     # dst dynamically, because Base.winprompt uses this function to
  354     # convert passwords to UTF-8 and we don't want to make unintentional
  355     # copies of the password data.
  356     a = src[1]
  357     i, m = 1, 0
  358     while true
  359         if a < 0x80
  360             m += 1
  361         elseif a < 0x800 # 2-byte UTF-8
  362             m += 2
  363         elseif a & 0xfc00 == 0xd800 && i < length(src)
  364             b = src[i += 1]
  365             if (b & 0xfc00) == 0xdc00 # 2-unit UTF-16 sequence => 4-byte UTF-8
  366                 m += 4
  367             else
  368                 m += 3
  369                 a = b; continue
  370             end
  371         else
  372             # 1-unit high UTF-16 or unpaired high surrogate
  373             # either way, encode as 3-byte UTF-8 code point
  374             m += 3
  375         end
  376         i < n || break
  377         a = src[i += 1]
  378     end
  379 
  380     dst = StringVector(m)
  381     a = src[1]
  382     i, j = 1, 0
  383     while true
  384         if a < 0x80 # ASCII
  385             dst[j += 1] = a % UInt8
  386         elseif a < 0x800 # 2-byte UTF-8
  387             dst[j += 1] = 0xc0 | ((a >> 6) % UInt8)
  388             dst[j += 1] = 0x80 | ((a % UInt8) & 0x3f)
  389         elseif a & 0xfc00 == 0xd800 && i < n
  390             b = src[i += 1]
  391             if (b & 0xfc00) == 0xdc00
  392                 # 2-unit UTF-16 sequence => 4-byte UTF-8
  393                 a += 0x2840
  394                 dst[j += 1] = 0xf0 | ((a >> 8) % UInt8)
  395                 dst[j += 1] = 0x80 | ((a % UInt8) >> 2)
  396                 dst[j += 1] = xor(0xf0, ((a % UInt8) << 4) & 0x3f, (b >> 6) % UInt8)
  397                 dst[j += 1] = 0x80 | ((b % UInt8) & 0x3f)
  398             else
  399                 dst[j += 1] = 0xe0 | ((a >> 12) % UInt8)
  400                 dst[j += 1] = 0x80 | (((a >> 6) % UInt8) & 0x3f)
  401                 dst[j += 1] = 0x80 | ((a % UInt8) & 0x3f)
  402                 a = b; continue
  403             end
  404         else
  405             # 1-unit high UTF-16 or unpaired high surrogate
  406             # either way, encode as 3-byte UTF-8 code point
  407             dst[j += 1] = 0xe0 | ((a >> 12) % UInt8)
  408             dst[j += 1] = 0x80 | (((a >> 6) % UInt8) & 0x3f)
  409             dst[j += 1] = 0x80 | ((a % UInt8) & 0x3f)
  410         end
  411         i < n || break
  412         a = src[i += 1]
  413     end
  414     return dst
  415 end
  416 
  417 # deferring (or un-deferring) ctrl-c handler for external C code that
  418 # is not interrupt safe (see also issue #2622).  The sigatomic_begin/end
  419 # functions should always be called in matched pairs, ideally via:
  420 #            disable_sigint() do .. end
  421 # reennable_sigint is provided so that immediate ctrl-c handling is
  422 # re-enabled within a sigatomic region, e.g. inside a Julia callback function
  423 # within a long-running C routine.
  424 sigatomic_begin() = ccall(:jl_sigatomic_begin, Cvoid, ())
  425 sigatomic_end() = ccall(:jl_sigatomic_end, Cvoid, ())
  426 
  427 """
  428     disable_sigint(f::Function)
  429 
  430 Disable Ctrl-C handler during execution of a function on the current task,
  431 for calling external code that may call julia code that is not interrupt safe.
  432 Intended to be called using `do` block syntax as follows:
  433 
  434     disable_sigint() do
  435         # interrupt-unsafe code
  436         ...
  437     end
  438 
  439 This is not needed on worker threads (`Threads.threadid() != 1`) since the
  440 `InterruptException` will only be delivered to the master thread.
  441 External functions that do not call julia code or julia runtime
  442 automatically disable sigint during their execution.
  443 """
  444 function disable_sigint(f::Function)
  445     sigatomic_begin()
  446     res = f()
  447     # Exception unwind sigatomic automatically
  448     sigatomic_end()
  449     res
  450 end
  451 
  452 """
  453     reenable_sigint(f::Function)
  454 
  455 Re-enable Ctrl-C handler during execution of a function.
  456 Temporarily reverses the effect of [`disable_sigint`](@ref).
  457 """
  458 function reenable_sigint(f::Function)
  459     sigatomic_end()
  460     res = f()
  461     # Exception unwind sigatomic automatically
  462     sigatomic_begin()
  463     res
  464 end
  465 
  466 function ccallable(f::Function, rt::Type, argt::Type, name::Union{AbstractString,Symbol}=string(f))
  467     ccall(:jl_extern_c, Cvoid, (Any, Any, Any, Cstring), f, rt, argt, name)
  468 end
  469 
  470 function expand_ccallable(rt, def)
  471     if isa(def,Expr) && (def.head === :(=) || def.head === :function)
  472         sig = def.args[1]
  473         if sig.head === :(::)
  474             if rt === nothing
  475                 rt = sig.args[2]
  476             end
  477             sig = sig.args[1]
  478         end
  479         if rt === nothing
  480             error("@ccallable requires a return type")
  481         end
  482         if sig.head === :call
  483             name = sig.args[1]
  484             at = map(sig.args[2:end]) do a
  485                 if isa(a,Expr) && a.head === :(::)
  486                     a.args[2]
  487                 else
  488                     :Any
  489                 end
  490             end
  491             return quote
  492                 $(esc(def))
  493                 ccallable($(esc(name)), $(esc(rt)), $(Expr(:curly, :Tuple, map(esc, at)...)), $(string(name)))
  494             end
  495         end
  496     end
  497     error("expected method definition in @ccallable")
  498 end
  499 
  500 macro ccallable(def)
  501     expand_ccallable(nothing, def)
  502 end
  503 macro ccallable(rt, def)
  504     expand_ccallable(rt, def)
  505 end