Взаимодействие с Си¶
В Ü имеется ограниченная возможность взаимодействовать с кодом на Си. Можно вызывать функции, написанные на Си из Ü. Также можно вызывать функции, написанные на Ü из Си.
Для взаимодействия с Си в Ü есть ряд механизмов.
Функции без кодирования имён¶
В отличие от Си, в Ü имена обычных функции специальным образом кодируются, чтобы итоговые полные имена перегруженных функций или функций в различных пространствах имён различались.
Чтобы отменить такое кодирование, надо пометить функцию модификатором nomangle
, указанным после fn
и опционального модификатора constexpr
.
Имя функции, помещенное таким образом, будет тем же, каким бы оно было в Си. Соответственно, такую функцию можно будет вызвать из Си.
Также можно будет пометить таким образом прототип функции, реализованной на Си, для возможности вызова её из Ü.
fn nomangle SDL_Quit() : void;
fn MyQuit()
{
SDL_Quit(); // Вызываем внешнюю функцию
}
// Функция, доступная в Си коде
fn nomangle SomeFoo() : i32
{
return 0;
}
nomangle
функции имеют ряд ограничений:
- Операторы не могут быть
nomangle
- Функции-члены структур или классов не могут быть
nomangle
nomangle
функции могут быть расположены только в глобальном пространстве имён- Нельзя перегружать
nomangle
функции
Cоглашения о вызове¶
Функции и указатели на функию могут иметь указание соглашения о вызове.
Оно указывается после перечисления списка параметров функции и после unsafe
(если таковой есть).
fn Foo() call_conv("C");
fn Bar(i32 x) unsafe call_conv("fast") {}
fn nomangle Baz(f32 x, f32 y) call_conv("system"){}
var (fn() call_conv("C")) ptr = Foo;
Существуют следующие имена соглашений о вызовах: C
, default
, Ü
, fast
, cold
, system
.
C
- стандартное соглашение о вызове, использующееся в языках Си и C++.
default
и Ü
это псевдонимы для C
.
Также, если не указано соглашение о вызове, оно будет равно C
.
Для взаимодействия с Си и C++ кодом следует использовать именно это соглашение о вызове.
fast
и cold
- соглашения для соответственно быстрого или компактного вызова.
Они не совместимы со схожими соглашениями в других языках, так что использовать их можно только в Ü коде, и то, если это даёт ощутимый эффект.
system
- это платформозависимый псевдоним для системных функций.
На большинстве платформ это псевдоним для соглашения C
.
На 32-битной Windows это псевдоним для stdcall
соглашения, которое используется в WinAPI.
Структуры с упорядоченными полями¶
Обычные структуры и классы в Ü имеют неопределённый порядок полей. Компилятор имеет право упорядочить их, как ему удобно.
В Си же поведение иное - поля структур там упорядочены в порядке объявления.
Для того, чтобы получить порядок полей структур, как в Си, существует специальный модификатор - ordered
.
Данный модификатор указывается при объявлении структуры или класса, после опциональных вида класса, родительских классов, модификатора non_sync
.
Структура объявленная с таким модификатором будет иметь тот же порядок полей, что аналогичная структура в Си.
В примере ниже две данные структуры будут аналогичны.
struct A ordered
{
bool x;
i32 y;
bool z;
}
struct A
{
bool x;
int32_t y;
bool z;
};
Ограничения и предостережения взаимодействия с Си¶
Не каждую функцию на Ü можно вызвать из Си и наоборот. Существует ряд ограничений, накладываемых на вызов. Компилятор Ü не знает, что какая-та функция реализована на Си, и поэтому не может проверить правильность вызова. Поэтому соблюдение правил возложено на программиста.
Аргументы-значения и возвращаемые значения функций должны быть фундаментального типа, типа перечисления, типа указателя на функцию или сырого указателя. Составные типы (структуры/классы, массивы, кортежи) для значений не поддерживаются. При этом можно передавать в функцию и возвращать из функции ссылки, они аналогичны указателям в Си.
Структуры, передаваемые в Си код, или получаемые из него, должны иметь одинаковый состав и порядок полей в Ü и в Си. Исключения составляют структуры, к полям которых нету обращений из Ü и которые передаются в Си по одиночке (не массивом). Такие структуры могут не иметь аналогичного состава полей, главное, чтобы их размер и выравнивание были не меньше, чем в Си.
Кортежи в Ü по размещению в памяти аналогичны структурам в Си, с тем же набором и порядком типов элементов, что в кортеже. Поэтому в Си коде следует использовать структуры-аналоги для кортежей Ü.
В Си коде не действует контроль ссылок. Поэтому надо быть особо внимательным при взаимодействии с Си кодом.
Для большей безопасности рекомендуется помечать как unsafe
функции, реализованные на Си.
Это заставит пользователя таких функций оборачивать вызов этих функций в unsafe
блок и придаст больше внимательности.