Интерфейс C

# 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.

Каждое argvalue для @ccall преобразуется в соответствующий argtype путем автоматической вставки вызовов unsafe_convert(argtype, cconvert(argtype, argvalue)). (Дополнительные сведения см. в документации по unsafe_convert и cconvert.) В большинстве случаев это просто приводит к вызову convert(argtype, argvalue).

Примеры

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

Здесь вызывается функция стандартной библиотеки С

size_t strlen(char *)

с переменной Julia с именем s. См. также ccall.

Varargs поддерживаются со следующей конвенцией.

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

Точка с запятой используется для отделения обязательных аргументов (которых должно быть не менее одного) от переменного числа аргументов.

Пример использования внешней библиотеки:

# C signature of g_uri_escape_string:
# 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(....

# 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.

Обратите внимание, что кортеж типа аргумента должен быть литеральным кортежем, а не переменной или выражением со значением кортежа.

Каждое argvalue для ccall преобразуется в соответствующий argtype путем автоматической вставки вызовов unsafe_convert(argtype, cconvert(argtype, argvalue)). (Дополнительные сведения см. в документации по unsafe_convert и cconvert.) В большинстве случаев это просто приводит к вызову convert(argtype, argvalue).

# Core.Intrinsics.cglobalFunction

cglobal((symbol, library) [, type=Cvoid])

Получает указатель на глобальную переменную в экспортированной из C общей библиотеке, заданной явным образом как в ccall. Возвращает Ptr{Type}. По умолчанию используется Ptr{Cvoid}, если аргумент Type не указан. Значения могут быть считаны или записаны с помощью unsafe_load или unsafe_store!, соответственно.

# Base.@cfunctionMacro

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

Создает указатель функции с поддержкой C из функции Julia callable для заданной сигнатуры типа. Для передачи возвращаемого значения в ccall используйте в сигнатуре тип аргумента Ptr{Cvoid}.

Обратите внимание, что кортеж типа аргумента должен быть литеральным кортежем, а не переменной или выражением со значением кортежа (хотя он может содержать выражение с символом), и что эти аргументы будут вычислены в глобальной области во время компиляции (а не отложены до времени выполнения). Добавление $ перед аргументом функции приводит к изменению вместо закрытия среды выполнения для локальной переменной callable (поддерживается не во всех архитектурах).

Примеры

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

julia> @cfunction(foo, Int, (Int, Int))
Ptr{Cvoid} @0x000000001b82fcd0

# Base.CFunctionType

CFunction struct

Обработчик сбора мусора для возвращаемого значения из @cfunction, когда первый аргумент аннотирован $. Как и все обработчики cfunction, он должен быть передан ccall как Ptr{Cvoid}, и будет автоматически преобразован в соответствующий тип на месте вызова.

См. описание @cfunction.

# Base.unsafe_convertFunction

unsafe_convert(T, x)

Преобразует x в аргумент C типа T, где входной x должен быть возвращаемым значением cconvert(T, ...).

В случаях, когда convert необходимо принять объект Julia и преобразовать его в Ptr, эта функция должна использоваться для определения и выполнения такого преобразования.

Следите за тем, чтобы ссылка Julia на x существовала в течение всего времени использования результата этой функции. Соответственно, аргумент x этой функции никогда не должен быть выражением. Он должен быть только именем переменной или ссылкой на поле. Например, x=a.b.c является допустимым вариантом, а x=[a,b,c] — нет.

Префикс unsafe в этой функции указывает на то, что использование результата этой функции после того, как ее аргумент x будет больше не доступен для программы, может привести к неопределенному поведению, включая повреждение или аварийное завершение программы, в более позднее время.

См. также описание cconvert.

# Base.cconvertFunction

cconvert(T,x)

Преобразует x в значение, передаваемое коду C в качестве типа T, обычно путем вызова convert(T, x).

В случаях, когда x невозможно преобразовать в T, cconvert, в отличие от convert, может возвратить объект с типом, отличным от T, который, тем не менее, подходит unsafe_convert для обработки. Результат этой функции должен оставаться допустимым (для сборки мусора) до тех пор, пока результат unsafe_convert больше не понадобится. Это можно использовать для выделения памяти, к которой будет обращаться ccall. Если необходимо выделить несколько объектов, в качестве возвращаемого значения можно использовать кортеж объектов.

Ни convert, ни cconvert не должны принимать объект Julia и преобразовывать его в Ptr.

# Base.unsafe_loadFunction

unsafe_load(p::Ptr{T}, i::Integer=1)

Загрузка значения типа T с адреса i-го элемента (с индексированием от 1), начиная с p. Эквивалентно выражению C p[i-1].

Префикс unsafe в этой функции указывает на то, что проверка, гарантирующая допустимость указателя p, не выполняется. Как и в C, программист отвечает за то, чтобы при вызове этой функции память, на которую указывает ссылка, не освобождалась и не собирался мусор. Неправильное использование может привести к аварийному завершению программы или возвращению «мусорных» ответов. В отличие от C, разыменование области памяти, выделенной в виде другого типа, может быть корректным при условии, что эти типы совместимы.

# Base.unsafe_store!Function

unsafe_store!(p::Ptr{T}, x, i::Integer=1)

Хранит значение типа T по адресу i-го элемента (с индексированием от 1), начиная с p. Эквивалентно выражению C p[i-1] = x.

Префикс unsafe в этой функции указывает на то, что проверка, гарантирующая допустимость указателя p, не выполняется. Как и в C, программист отвечает за то, чтобы при вызове этой функции память, на которую указывает ссылка, не освобождалась и не собирался мусор. Неправильное использование может привести к аварийному завершению программы. В отличие от C, хранение области памяти, выделенной в виде другого типа, может быть корректным при условии, что эти типы совместимы.

# Base.unsafe_copyto!Method

unsafe_copyto!(dest::Ptr{T}, src::Ptr{T}, N)

Копирует элементы N из исходного указателя в конечный без проверки. Размер элемента определяется типом указателей.

Префикс unsafe в этой функции указывает на то, что проверка, гарантирующая допустимость указателей dest и src, не выполняется. Неправильное использование может привести к повреждению или аварийному завершению программы точно так же, как и в C.

# Base.unsafe_copyto!Method

unsafe_copyto!(dest::Array, do, src::Array, so, N)

Копирует элементы N из исходного массива в конечный, начиная с линейного индекса so в источнике и do в месте назначения (с индексированием от 1).

Префикс unsafe в этой функции указывает на то, что проверка, гарантирующая, что N находится в границах любого массива, не выполняется. Неправильное использование может привести к повреждению или аварийному завершению программы точно так же, как и в C.

# Base.copyto!Function

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

Копирует элементы N из коллекции src, начиная с линейного индекса so, в массив dest, начиная с индекса do. Возвращает dest.

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

Копирует все элементы из коллекции src в массив dest, длина которого должна быть больше или равна длине n для src. Первые n элементов dest перезаписываются, остальные не затрагиваются.

См. также описание copy! и copy.

Примеры

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
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
copyto!(dest::AbstractMatrix, src::UniformScaling)

Копирует UniformScaling в матрицу.

Совместимость: Julia 1.1

В Julia 1.0 этот метод поддерживал только квадратную матрицу назначения. В Julia 1.1. добавлена поддержка прямоугольной матрицы.

# Base.pointerFunction

pointer(array [, index])

Получает собственный адрес массива или строки (при необходимости по index заданного расположения).

Эта функция небезопасна. Следите за тем, чтобы ссылка Julia на array существовала в течение всего времени использования указателя. Макрос GC.@preserve следует использовать для защиты аргумента array для сбора мусора в рамках заданного блока кода.

Обычно наиболее предпочтительным вариантом является вызов Ref(array[, index]), так как при этом гарантируется достоверность результата.

# Base.unsafe_wrapMethod

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

Заключает в объект Array Julia данные, заданные pointer, без создания копии. Тип элементов указателя T определяет тип элементов массива. dims является либо целочисленным (для одномерного массива), либо кортежем измерений массива. own необязательно указывает, должен ли язык Julia принять право собственности на память, вызывая free для указателя, когда на массив уже отсутствует ссылка.

Эта функция помечена как «небезопасная», потому что она завершится сбоем, если pointer не является допустимым адресом памяти для данных запрашиваемой длины. В отличие от unsafe_load и unsafe_store!, программист также отвечает за то, чтобы доступ к базовым данным не осуществлялся через два массива с разными типами элементов, подобно строгому правилу назначения псевдонимов в C.

# Base.pointer_from_objrefFunction

pointer_from_objref(x)

Получает адрес памяти объекта Julia в виде Ptr. Существование результирующего Ptr не защитит объект от сборки мусора, поэтому необходимо гарантировать, что на объект будет указывать ссылка в течение всего времени использования Ptr.

Эту функцию невозможно вызвать для неизменяемых объектов, поскольку у них отсутствуют стабильные адреса памяти.

См. также описание unsafe_pointer_to_objref.

# Base.unsafe_pointer_to_objrefFunction

unsafe_pointer_to_objref(p::Ptr)

Преобразует Ptr в ссылку на объект. Предполагается, что указатель ссылается на допустимый выделяемый в куче объект Julia. Если это не так, начинает действовать неопределенное поведение, поэтому данная функция считается «небезопасной» и должна использоваться с осторожностью.

См. также описание pointer_from_objref.

# Base.disable_sigintFunction

disable_sigint(f::Function)

Отключает обработчик Ctrl-C во время выполнения функции в текущей задаче для вызова внешнего кода, который может вызывать код Julia, не безопасный для прерываний. Предназначена для вызова с использованием синтаксиса блока do следующим образом:

disable_sigint() do
    # код, небезопасный для прерываний
    ...
end

Не предназначена для рабочих потоков (Threads.threadid() != 1), поскольку InterruptException доставляется только в главный поток. Внешние функции, которые не вызывают код или среду выполнения Julia, автоматически отключают сигнальную разведку во время своего выполнения.

# Base.reenable_sigintFunction

reenable_sigint(f::Function)

Повторно включает обработчик Ctrl-C во время выполнения функции. Временно отменяет эффект действия disable_sigint.

# Base.exit_on_sigintFunction

exit_on_sigint(on::Bool)

Устанавливает флаг exit_on_sigint среды выполнения Julia. Если false, Ctrl-C (SIGINT) фиксируется как InterruptException в блоке try. Это поведение по умолчанию в REPL, любой код выполняется с параметрами -e и -E, а скрипт Julia — с параметром -i.

Если true, Ctrl-C не вызывает InterruptException. Для выполнения кода при таком событии требуется atexit. Это поведение по умолчанию для выполнения скрипта Julia без параметра -i.

Совместимость: Julia 1.5

Для функции exit_on_sigint требуется версия Julia не ниже 1.5.

# Base.systemerrorFunction

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

Вызывает SystemError для errno со строкой с описанием sysfunc, если iftrue имеет значение true.

# Base.windowserrorFunction

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

Аналогична systemerror, но применяется для функций API Windows, использующих GetLastError для возвращения ошибки кода вместо задания errno.

# Core.PtrType

Ptr{T}

Адрес памяти, относящийся к данным тип T. Однако нет никакой гарантии, что память действительно является допустимой или что она представляет данные указанного типа.

# Core.RefType

Ref{T}

Объект, который безопасно ссылается на данные типа T. Этот тип гарантированно указывает на допустимую выделенную в Julia память правильного типа. Базовые данные защищены от освобождения сборщиком мусора до тех пор, пока существует ссылка на Ref.

В Julia объекты Ref разыменовываются (загружаются или хранятся) с помощью [].

Создание Ref со значением x типа T обычно записывается как Ref(x). Кроме того, при создании внутренних указателей на контейнеры (такие как Array или Ptr) функцию можно записать как Ref(a, i) для создания ссылки на i-й элемент a.

Ref{T}() создает ссылку на значение типа T без инициализации. Для битового типа T значением будет то, что в данный момент находится в выделенной памяти. Для небитового типа T ссылка будет неопределенной, и попытка ее разыменования приведет к ошибке «UndefRefError: доступ к неопределенной ссылке».

Чтобы проверить, является ли Ref неопределенной ссылкой, следует использовать isassigned(ref::RefValue). Например, isassigned(Ref{T}()) имеет значение false, если T является небитовым типом. Если T является битовым типом, isassigned(Ref{T}()) всегда будет иметь значение true.

При передаче в качестве аргумента ccall (типа Ptr или Ref) объект Ref будет преобразовывать в собственный указатель данные, на которые он ссылается. Для большинства T или при преобразовании в Ptr{Cvoid} объект будет указателем на данные объекта. Если T имеет тип isbits, это значение можно легко изменять, в противном случае изменение является строго неопределенным поведением.

Как частный случай, задание T = Any приведет к созданию указателя на саму ссылку при преобразовании в Ptr{Any} (jl_value_t const* const*, если T является неизменяемым, в противном случае — jl_value_t *const *). При преобразовании Ptr{Cvoid} будет по-прежнему возвращаться указатель области данных, как и для других T.

Экземпляр C_NULL Ptr можно передать аргументу Ref ccall для его инициализации.

Использование в трансляции

Ref иногда используется в трансляции для того, чтобы значения, на которые указывает ссылка, рассматривались как скалярные.

Примеры

julia> Ref(5)
Base.RefValue{Int64}(5)

julia> isa.(Ref([1,2,3]), [Array, Dict, Int]) # Считает значения, на которые указывает ссылка, скалярными во время трансляции
3-element BitVector:
 1
 0
 0

julia> Ref{Function}()  # Неопределенная ссылка на небитовый тип, функция
Base.RefValue{Function}(#undef)

julia> try
           Ref{Function}()[] # Разыменование неопределенной ссылки приведет к ошибке
       catch e
           println(e)
       end
UndefRefError()

julia> Ref{Int64}()[]; # Ссылка на битовый тип относится к неопределенному значению, если оно не задано

julia> isassigned(Ref{Int64}()) # Ссылка на битовый тип всегда присваивается
true

julia> Ref{Int64}(0)[] == 0 # Явно задать значения для ссылки на битовый тип
true

# 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

# Base.CcharType

Cchar

Аналогичен собственному типу C char.

# Base.CucharType

Cuchar

Аналогичен собственному типу C unsigned char (UInt8).

# Base.CshortType

Cshort

Аналогичен собственному типу C signed short (Int16).

# Base.CstringType

Cstring

Строка в стиле C, состоящая из Cchar собственного типа подстановочных знаков. Cstring завершаются нулевым символом. О строках в стиле C, состоящих из собственных типов см. в разделе о Cwstring. Дополнительные сведения о взаимодействии строк с C см. в этом руководстве.

# Base.CushortType

Cushort

Аналогичен собственному типу C unsigned short (UInt16).

# Base.CintType

Cint

Аналогичен собственному типу C signed int (Int32).

# Base.CuintType

Cuint

Аналогичен собственному типу C unsigned int (UInt32).

# Base.ClongType

Clong

Аналогичен собственному типу C signed long.

# Base.CulongType

Culong

Аналогичен собственному типу C unsigned long.

# Base.ClonglongType

Clonglong

Аналогичен собственному типу C signed long long (Int64).

# Base.CulonglongType

Culonglong

Аналогичен собственному типу C unsigned long long (UInt64).

# Base.Cintmax_tType

Cintmax_t

Аналогичен собственному типу C intmax_t (Int64).

# Base.Cuintmax_tType

Cuintmax_t

Аналогичен собственному типу C uintmax_t (UInt64).

# Base.Csize_tType

Csize_t

Аналогичен собственному типу C size_t (UInt).

# Base.Cssize_tType

Cssize_t

Аналогичен собственному типу C ssize_t.

# Base.Cptrdiff_tType

Cptrdiff_t

Аналогичен собственному типу C ptrdiff_t (Int).

# Base.Cwchar_tType

Cwchar_t

Аналогичен собственному типу C wchar_t (Int32).

# Base.CwstringType

Cwstring

Строка в стиле C, состоящая из Cwchar_t собственного типа подстановочных знаков. Cwstring завершаются нулевым символом.о строках в стиле C, состоящих из собственных типов символов, см. в разделе о Cstring. Дополнительные сведения о взаимодействии строк с C см. в этом руководстве.

# Base.CfloatType

Cfloat

Аналогичен собственному типу C float (Float32).

# Base.CdoubleType

Cdouble

Аналогичен собственному типу C double (Float64).

Интерфейс LLVM

# 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 уровня функции (аналогично блоку define LLVM), с аргументами, доступными в виде последовательных безымянных переменных SSA (%0, %1 и т. д.);

  • в виде двухэлементного кортежа, содержащего строку модуля среды IR и строку, представляющую имя вызываемой функции точки входа;

  • в виде двухэлементного кортежа с модулем, представленным в виде Vector{UInt8} с битовым кодом.

Обратите внимание, что в отличие от ccall, типы аргументов должны быть указаны как тип кортежа, а не кортеж типов. Все типы, а также код LLVM, должны быть указаны как литералы, а не переменные или выражения (для создания этих литералов может потребоваться использовать @eval ).

См. test/llvmcall.jl с примерами использования.