C Interface

Base.@ccallMacro
@ccall library.function_name(argvalue1::argtype1, ...)::returntype
@ccall function_name(argvalue1::argtype1, ...)::returntype
@ccall $function_pointer(argvalue1::argtype1, ...)::returntype

在 C 导出的共享库中调用一个函数,由 library.function_name 指定,其中 library 是一个字符串常量或字面量。可以省略库名,在这种情况下,function_name 在当前进程中解析。或者,@ccall 也可以用于调用一个函数指针 $function_pointer,例如由 dlsym 返回的指针。

每个传递给 @ccallargvalue 都会通过自动插入调用 unsafe_convert(argtype, cconvert(argtype, argvalue)) 转换为相应的 argtype。(有关详细信息,请参见 unsafe_convertcconvert 的文档。)在大多数情况下,这仅仅导致调用 convert(argtype, argvalue)

示例

@ccall strlen(s::Cstring)::Csize_t

这调用 C 标准库函数:

size_t strlen(char *)

使用名为 s 的 Julia 变量。另请参见 ccall

支持可变参数,使用以下约定:

@ccall printf("%s = %d"::Cstring ; "foo"::Cstring, foo::Cint)::Cint

分号用于将必需参数(至少必须有一个)与可变参数分开。

使用外部库的示例:

# g_uri_escape_string 的 C 签名:
# char *g_uri_escape_string(const char *unescaped, const char *reserved_chars_allowed, gboolean allow_utf8);

const glib = "libglib-2.0"
@ccall glib.g_uri_escape_string(my_uri::Cstring, ":/"::Cstring, true::Cint)::Cstring

如果需要,字符串字面量也可以直接在函数名之前使用,例如 "libglib-2.0".g_uri_escape_string(...

source
ccallKeyword
ccall((function_name, library), returntype, (argtype1, ...), argvalue1, ...)
ccall(function_name, returntype, (argtype1, ...), argvalue1, ...)
ccall(function_pointer, returntype, (argtype1, ...), argvalue1, ...)

调用在 C 导出共享库中的函数,由元组 (function_name, library) 指定,其中每个组件可以是字符串或符号。除了指定库外,还可以使用 function_name 符号或字符串,这将在当前进程中解析。或者,ccall 也可以用于调用函数指针 function_pointer,例如由 dlsym 返回的指针。

请注意,参数类型元组必须是字面量元组,而不是元组值变量或表达式。

每个传递给 ccallargvalue 将通过自动插入调用 unsafe_convert(argtype, cconvert(argtype, argvalue)) 转换为相应的 argtype。(有关详细信息,请参见 unsafe_convertcconvert 的文档。)在大多数情况下,这仅会导致对 convert(argtype, argvalue) 的调用。

source
Core.Intrinsics.cglobalFunction
cglobal((symbol, library) [, type=Cvoid])

获取指向在 C 导出的共享库中的全局变量的指针,指定方式与 ccall 完全相同。如果未提供 Type 参数,则默认返回 Ptr{Cvoid}。可以通过 unsafe_loadunsafe_store! 分别读取或写入这些值。

source
Base.@cfunctionMacro
@cfunction(callable, ReturnType, (ArgumentTypes...,)) -> Ptr{Cvoid}
@cfunction($callable, ReturnType, (ArgumentTypes...,)) -> CFunction

生成一个 C 可调用的函数指针,从给定类型签名的 Julia 函数 callable。要将返回值传递给 ccall,请在签名中使用参数类型 Ptr{Cvoid}

请注意,参数类型元组必须是字面量元组,而不是元组值变量或表达式(尽管它可以包含展开表达式)。并且这些参数将在编译时在全局作用域中进行评估(而不是推迟到运行时)。在函数参数前添加 '$' 会将其更改为在局部变量 callable 上创建一个运行时闭包(这并不支持所有架构)。

请参阅 manual section on ccall and cfunction usage

示例

julia> function foo(x::Int, y::Int)
           return x + y
       end

julia> @cfunction(foo, Int, (Int, Int))
Ptr{Cvoid} @0x000000001b82fcd0
source
Base.CFunctionType
CFunction 结构体

用于处理从 @cfunction 返回值的垃圾回收句柄,当第一个参数用 '$' 注释时。像所有 cfunction 句柄一样,它应该作为 Ptr{Cvoid} 传递给 ccall,并将在调用点自动转换为适当的类型。

请参见 @cfunction

source
Base.unsafe_convertFunction
unsafe_convert(T, x)

x 转换为类型 T 的 C 参数,其中输入 x 必须是 cconvert(T, ...) 的返回值。

在需要 convert 将 Julia 对象转换为 Ptr 的情况下,应使用此函数来定义和执行该转换。

请小心确保在此函数的结果被使用期间,x 的 Julia 引用存在。因此,此函数的参数 x 不应是表达式,只应是变量名或字段引用。例如,x=a.b.c 是可接受的,但 x=[a,b,c] 则不可接受。

此函数的 unsafe 前缀表示,在此函数的 x 参数不再可被程序访问后使用此函数的结果可能会导致未定义行为,包括程序损坏或段错误,在任何后续时间。

另请参见 cconvert

source
Base.cconvertFunction
cconvert(T,x)

x 转换为可以作为类型 T 传递给 C 代码的值,通常通过调用 convert(T, x) 实现。

x 不能安全地转换为 T 的情况下,与 convert 不同,cconvert 可能返回一个与 T 不同类型的对象,但该对象适合由 unsafe_convert 处理。此函数的结果在 unsafe_convert 不再需要之前应保持有效(以便于 GC)。这可以用于分配将被 ccall 访问的内存。如果需要分配多个对象,可以将这些对象的元组用作返回值。

convertcconvert 都不应将 Julia 对象转换为 Ptr

source
Base.unsafe_loadFunction
unsafe_load(p::Ptr{T}, i::Integer=1)
unsafe_load(p::Ptr{T}, order::Symbol)
unsafe_load(p::Ptr{T}, i::Integer, order::Symbol)

从地址 p 开始的第 i 个元素(1 索引)加载类型 T 的值。这相当于 C 表达式 p[i-1]。可以选择提供一个原子内存顺序。

此函数的 unsafe 前缀表示不会对指针 p 进行验证以确保其有效性。与 C 一样,程序员有责任确保在调用此函数时引用的内存未被释放或垃圾回收。错误的使用可能会导致程序段错误或返回垃圾答案。与 C 不同的是,解引用分配为不同类型的内存区域可能是有效的,只要这些类型是兼容的。

Julia 1.10

order 参数自 Julia 1.10 起可用。

另请参见: atomic

source
Base.unsafe_store!Function
unsafe_store!(p::Ptr{T}, x, i::Integer=1)
unsafe_store!(p::Ptr{T}, x, order::Symbol)
unsafe_store!(p::Ptr{T}, x, i::Integer, order::Symbol)

将类型为 T 的值存储到从 p 开始的第 i 个元素(1 索引)地址中。这相当于 C 表达式 p[i-1] = x。可以选择提供一个原子内存顺序。

此函数的 unsafe 前缀表示不会对指针 p 进行验证以确保其有效性。与 C 一样,程序员有责任确保在调用此函数时引用的内存未被释放或垃圾回收。错误的使用可能会导致程序段错误。与 C 不同的是,只要类型兼容,将不同类型分配的内存区域存储可能是有效的。

Julia 1.10

order 参数自 Julia 1.10 起可用。

另请参见: atomic

source
Base.unsafe_modify!Function
unsafe_modify!(p::Ptr{T}, op, x, [order::Symbol]) -> Pair

这些操作原子地执行以获取和设置内存地址,应用函数 op。如果硬件支持(例如,原子递增),这可能会优化为适当的硬件指令,否则其执行将类似于:

y = unsafe_load(p)
z = op(y, x)
unsafe_store!(p, z)
return y => z

此函数的 unsafe 前缀表示不会对指针 p 进行验证以确保其有效性。与 C 一样,程序员有责任确保在调用此函数时引用的内存未被释放或垃圾回收。错误的使用可能会导致程序段错误。

Julia 1.10

此函数至少需要 Julia 1.10。

另请参见: modifyproperty!, atomic

source
Base.unsafe_replace!Function
unsafe_replace!(p::Ptr{T}, expected, desired,
               [success_order::Symbol[, fail_order::Symbol=success_order]]) -> (; old, success::Bool)

这些操作原子地执行以获取并有条件地将内存地址设置为给定值。如果硬件支持,这可能会优化为适当的硬件指令,否则其执行将类似于:

y = unsafe_load(p, fail_order)
ok = y === expected
if ok
    unsafe_store!(p, desired, success_order)
end
return (; old = y, success = ok)

此函数的 unsafe 前缀表示不会对指针 p 进行验证以确保其有效性。与 C 一样,程序员有责任确保在调用此函数时引用的内存未被释放或垃圾回收。不正确的使用可能会导致程序段错误。

Julia 1.10

此函数至少需要 Julia 1.10。

另请参见: replaceproperty!, atomic

source
Base.unsafe_swap!Function
unsafe_swap!(p::Ptr{T}, x, [order::Symbol])

这些操作原子性地执行,以同时获取和设置内存地址。如果硬件支持,这可能会优化为适当的硬件指令,否则其执行将类似于:

y = unsafe_load(p)
unsafe_store!(p, x)
return y

此函数的 unsafe 前缀表示不会对指针 p 进行验证以确保其有效性。与 C 一样,程序员有责任确保在调用此函数时引用的内存未被释放或垃圾回收。不正确的使用可能会导致程序段错误。

Julia 1.10

此函数至少需要 Julia 1.10。

另请参见:swapproperty!, atomic

source
Base.unsafe_copyto!Method
unsafe_copyto!(dest::Ptr{T}, src::Ptr{T}, N)

从源指针复制 N 个元素到目标指针,不进行任何检查。元素的大小由指针的类型决定。

该函数的 unsafe 前缀表示不会对指针 destsrc 进行验证,以确保它们是有效的。错误的使用可能会损坏或导致程序崩溃,方式与 C 语言相同。

source
Base.unsafe_copyto!Method
unsafe_copyto!(dest::Array, do, src::Array, so, N)

从源数组复制 N 个元素到目标数组,从源数组的线性索引 so 和目标数组的 do 开始(1 索引)。

此函数的 unsafe 前缀表示不会执行任何验证以确保 N 在任一数组中都是有效的。错误的使用可能会损坏或导致程序段错误,类似于 C 语言的情况。

source
Base.copyto!Function
copyto!(B::AbstractMatrix, ir_dest::AbstractUnitRange, jr_dest::AbstractUnitRange,
        tM::AbstractChar,
        M::AbstractVecOrMat, ir_src::AbstractUnitRange, jr_src::AbstractUnitRange) -> B

高效地将矩阵 M 的元素复制到 B,条件是字符参数 tM 如下:

tM目标
'N'B[ir_dest, jr_dest]M[ir_src, jr_src]
'T'B[ir_dest, jr_dest]transpose(M)[ir_src, jr_src]
'C'B[ir_dest, jr_dest]adjoint(M)[ir_src, jr_src]

元素 B[ir_dest, jr_dest] 会被覆盖。此外,索引范围参数必须满足 length(ir_dest) == length(ir_src)length(jr_dest) == length(jr_src)

另见 copy_transpose!copy_adjoint!

source
copyto!(dest::AbstractMatrix, src::UniformScaling)

UniformScaling 复制到矩阵上。

Julia 1.1

在 Julia 1.0 中,此方法仅支持方形目标矩阵。Julia 1.1 添加了对矩形矩阵的支持。

source
copyto!(dest, do, src, so, N)

从集合 src 中从线性索引 so 开始复制 N 个元素到数组 dest 中,从索引 do 开始。返回 dest

source
copyto!(dest::AbstractArray, src) -> dest

将集合 src 中的所有元素复制到数组 dest,其长度必须大于或等于 src 的长度 ndest 的前 n 个元素将被覆盖,其他元素保持不变。

另请参见 copy!, copy

Warning

当任何被修改的参数与其他参数共享内存时,行为可能会出乎意料。

示例

julia> x = [1., 0., 3., 0., 5.];

julia> y = zeros(7);

julia> copyto!(y, x);

julia> y
7-element Vector{Float64}:
 1.0
 0.0
 3.0
 0.0
 5.0
 0.0
 0.0
source
copyto!(dest, Rdest::CartesianIndices, src, Rsrc::CartesianIndices) -> dest

src 中范围为 Rsrc 的块复制到 dest 中范围为 Rdest 的块。两个区域的大小必须匹配。

示例

julia> A = zeros(5, 5);

julia> B = [1 2; 3 4];

julia> Ainds = CartesianIndices((2:3, 2:3));

julia> Binds = CartesianIndices(B);

julia> copyto!(A, Ainds, B, Binds)
5×5 Matrix{Float64}:
 0.0  0.0  0.0  0.0  0.0
 0.0  1.0  2.0  0.0  0.0
 0.0  3.0  4.0  0.0  0.0
 0.0  0.0  0.0  0.0  0.0
 0.0  0.0  0.0  0.0  0.0
source
Base.pointerFunction
pointer(array [, index])

获取数组或字符串的原生地址,选项上可以指定给定位置 index

此函数是“非安全”的。请小心确保在使用此指针的整个过程中,Julia 对 array 的引用存在。应使用 GC.@preserve 宏来保护 array 参数在给定代码块内不被垃圾回收。

调用 Ref(array[, index]) 通常比此函数更可取,因为它保证了有效性。

source
Base.unsafe_wrapMethod
unsafe_wrap(Array, pointer::Ptr{T}, dims; own = false)

在给定的 pointer 地址上将一个 Julia Array 对象包装在数据周围,而不进行复制。指针元素类型 T 决定了数组元素类型。dims 可以是一个整数(用于一维数组)或一个数组维度的元组。own 可选地指定 Julia 是否应当拥有内存,当数组不再被引用时调用 free 释放指针。

此函数被标记为“unsafe”,因为如果 pointer 不是有效的内存地址,且数据长度不匹配,则会崩溃。与 unsafe_loadunsafe_store! 不同,程序员还需确保底层数据不会通过两种不同元素类型的数组进行访问,这类似于 C 语言中的严格别名规则。

source
Base.pointer_from_objrefFunction
pointer_from_objref(x)

获取Julia对象的内存地址作为Ptr。生成的Ptr的存在不会保护对象不被垃圾回收,因此您必须确保在使用Ptr的整个过程中对象保持被引用。

此函数不能在不可变对象上调用,因为它们没有稳定的内存地址。

另请参见unsafe_pointer_to_objref

source
Base.unsafe_pointer_to_objrefFunction
unsafe_pointer_to_objref(p::Ptr)

Ptr 转换为对象引用。假设指针指向一个有效的堆分配的 Julia 对象。如果不是这种情况,将导致未定义的行为,因此此函数被认为是“安全性不确定”,应谨慎使用。

另见 pointer_from_objref

source
Base.disable_sigintFunction
disable_sigint(f::Function)

在当前任务中执行函数时禁用 Ctrl-C 处理程序,以便调用可能会调用不安全的 julia 代码的外部代码。旨在使用 do 块语法调用,如下所示:

disable_sigint() do
    # 不安全的中断代码
    ...
end

在工作线程上不需要这样做(Threads.threadid() != 1),因为 InterruptException 只会发送到主线程。未调用 julia 代码或 julia 运行时的外部函数在执行期间会自动禁用 sigint。

source
Base.exit_on_sigintFunction
exit_on_sigint(on::Bool)

设置 julia 运行时的 exit_on_sigint 标志。如果为 false,则 Ctrl-C (SIGINT) 可以在 try 块中捕获为 InterruptException。这是 REPL 中的默认行为,通过 -e-E 运行的任何代码,以及使用 -i 选项运行的 Julia 脚本。

如果为 true,则 Ctrl-C 不会抛出 InterruptException。在此事件发生时运行代码需要 atexit。这是在没有 -i 选项运行的 Julia 脚本中的默认行为。

Julia 1.5

函数 exit_on_sigint 至少需要 Julia 1.5。

source
Base.systemerrorFunction
systemerror(sysfunc[, errno::Cint=Libc.errno()])
systemerror(sysfunc, iftrue::Bool)

如果 iftruetrue,则为 errno 引发一个 SystemError,并使用描述性字符串 sysfunc

source
Base.windowserrorFunction
windowserror(sysfunc[, code::UInt32=Libc.GetLastError()])
windowserror(sysfunc, iftrue::Bool)

类似于 systemerror,但用于 Windows API 函数,这些函数使用 GetLastError 返回错误代码,而不是设置 errno

source
Core.PtrType
Ptr{T}

一个指向类型 T 数据的内存地址。然而,并不能保证该内存实际上是有效的,或者它确实表示指定类型的数据。

source
Core.RefType
Ref{T}

一个安全引用类型为 T 的数据的对象。该类型保证指向有效的、由 Julia 分配的正确类型的内存。只要 Ref 本身被引用,底层数据就会受到垃圾收集器的保护,避免被释放。

在 Julia 中,Ref 对象通过 [] 进行解引用(加载或存储)。

创建一个指向类型为 T 的值 xRef 通常写作 Ref(x)。此外,对于创建指向容器(如 Array 或 Ptr)的内部指针,可以写作 Ref(a, i),用于创建对 a 的第 i 个元素的引用。

Ref{T}() 创建一个未初始化的类型为 T 的值的引用。对于位类型 T,该值将是当前在分配的内存中存在的任何内容。对于非位类型 T,引用将是未定义的,尝试解引用将导致错误,"UndefRefError: access to undefined reference"。

要检查一个 Ref 是否是未定义的引用,可以使用 isassigned(ref::RefValue)。例如,如果 T 不是位类型,则 isassigned(Ref{T}())false。如果 T 是位类型,则 isassigned(Ref{T}()) 将始终为 true。

当作为 ccall 参数传递(作为 PtrRef 类型)时,Ref 对象将被转换为指向其引用的数据的本机指针。对于大多数 T,或者当转换为 Ptr{Cvoid} 时,这是指向对象数据的指针。当 Tisbits 类型时,该值可以安全地被修改,否则修改将严格是未定义行为。

作为特例,设置 T = Any 将导致在转换为 Ptr{Any} 时创建指向引用本身的指针(如果 T 是不可变的,则为 jl_value_t const* const*,否则为 jl_value_t *const *)。当转换为 Ptr{Cvoid} 时,它仍将返回指向数据区域的指针,与任何其他 T 相同。

可以将 PtrC_NULL 实例传递给 ccallRef 参数以初始化它。

在广播中的使用

Ref 有时在广播中使用,以将引用的值视为标量。

示例

julia> r = Ref(5) # 创建一个具有初始值的 Ref
Base.RefValue{Int64}(5)

julia> r[] # 从 Ref 获取值
5

julia> r[] = 7 # 在 Ref 中存储新值
7

julia> r # Ref 现在包含 7
Base.RefValue{Int64}(7)

julia> isa.(Ref([1,2,3]), [Array, Dict, Int]) # 在广播期间将引用值视为标量
3-element BitVector:
 1
 0
 0

julia> Ref{Function}()  # 对非位类型 Function 的未定义引用
Base.RefValue{Function}(#undef)

julia> try
           Ref{Function}()[] # 解引用未定义引用将导致错误
       catch e
           println(e)
       end
UndefRefError()

julia> Ref{Int64}()[]; # 对位类型的引用如果未给出则引用一个未确定的值

julia> isassigned(Ref{Int64}()) # 对位类型的引用始终被赋值
true
source
Base.isassignedMethod
isassigned(ref::RefValue) -> Bool

测试给定的 Ref 是否与一个值相关联。对于位类型对象的 Ref,这总是为真。如果引用未定义,则返回 false

示例

julia> ref = Ref{Function}()
Base.RefValue{Function}(#undef)

julia> isassigned(ref)
false

julia> ref[] = (foobar(x) = x)
foobar (generic function with 1 method)

julia> isassigned(ref)
true

julia> isassigned(Ref{Int}())
true
source
Base.CstringType
Cstring

由本机字符类型 Cchar 组成的 C 风格字符串。Cstring 是以 NUL 结尾的。有关由本机宽字符类型组成的 C 风格字符串,请参见 Cwstring。有关与 C 的字符串互操作性的更多信息,请参见 manual

source
Base.CwstringType
Cwstring

由本机宽字符类型 Cwchar_t 组成的 C 风格字符串。Cwstring 是以 NUL 结尾的。有关由本机字符类型组成的 C 风格字符串,请参见 Cstring。有关与 C 的字符串互操作性的信息,请参见 manual

source

LLVM Interface

Core.Intrinsics.llvmcallFunction
llvmcall(fun_ir::String, returntype, Tuple{argtype1, ...}, argvalue1, ...)
llvmcall((mod_ir::String, entry_fn::String), returntype, Tuple{argtype1, ...}, argvalue1, ...)
llvmcall((mod_bc::Vector{UInt8}, entry_fn::String), returntype, Tuple{argtype1, ...}, argvalue1, ...)

调用第一个参数中提供的LLVM代码。可以通过几种方式指定此第一个参数:

  • 作为一个字面字符串,表示函数级别的IR(类似于LLVM的define块),其中参数作为连续的未命名SSA变量(%0, %1等)可用;
  • 作为一个包含模块IR字符串和表示要调用的入口点函数名称的字符串的2元素元组;
  • 作为一个2元素元组,但模块以Vector{UInt8}形式提供,包含位码。

请注意,与ccall相反,参数类型必须指定为元组类型,而不是类型的元组。所有类型以及LLVM代码都应作为字面量指定,而不是变量或表达式(可能需要使用@eval来生成这些字面量)。

不透明指针(写作ptr)在LLVM代码中是不允许的。

有关用法示例,请参见test/llvmcall.jl

source