Взаимодействие с Си

В Ü имеется ограниченная возможность взаимодействовать с кодом на Си. Можно вызывать функции, написанные на Си из Ü. Также можно вызывать функции, написанные на Ü из Си.

Для взаимодействия с Си в Ü есть ряд механизмов.

Функции без кодирования имён

В отличие от Си, в Ü имена обычных функции специальным образом кодируются, чтобы итоговые полные имена перегруженных функций или функций в различных пространствах имён различались. Чтобы отменить такое кодирование, надо пометить функцию модификатором nomangle, указанным после fn и опционального модификатора constexpr. Имя функции, помещенное таким образом, будет тем же, каким бы оно было в Си. Соответственно, такую функцию можно будет вызвать из Си. Также можно будет пометить таким образом прототип функции, реализованной на Си, для возможности вызова её из Ü.

fn nomangle SDL_Quit() : void;

fn MyQuit()
{
    SDL_Quit(); // Вызываем внешнюю функцию
}

// Функция, доступная в Си коде
fn nomangle SomeFoo() : i32
{
    return 0;
}

nomangle функции имеют ряд ограничений:

  • Операторы не могут быть nomangle
  • Функции-члены структур или классов не могут быть nomangle
  • nomangle функции могут быть расположены только в глобальном пространстве имён
  • Нельзя перегружать nomangle функции

Структуры с упорядоченными полями

Обычные структуры и классы в Ü имеют неопределённый порядок полей. Компилятор имеет право упорядочить их, как ему удобно. В Си же поведение иное - поля структур там упорядочены в порядке объявления. Для того, чтобы получить порядок полей структур, как в Си, существует специальный модификатор - ordered. Данный модификатор указывается при объявлении структуры или класса, после опциональных вида класса, родительских классов, модификатора shared. Структура объявленная с таким модификатором будет иметь тот же порядок полей, что аналогичная структура в Си.

В примере ниже две данные структуры будут аналогичны.

Ü код
 struct A ordered
 {
     bool x;
     i32 y;
     bool z;
 }
C++ код
 struct A
 {
     bool x;
     int32_t y;
     bool z;
 };

Ограничения и предостережения взаимодействия с Си

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

Аргументы-значения и возвращаемые значения функций должны быть фундаментального типа или иметь тип перечисления. Остальные типы для значений не поддерживаются. При этом можно передавать в функцию и возвращать из функции ссылки, они аналогичны указателям в Си.

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

Кортежи в Ü по размещению в памяти аналогичны структурам в Си, с тем же набором и порядком типов элементов, что в кортеже. Поэтому в Си коде следует использовать структуры-аналоги для кортежей Ü.

В Си коде не действует контроль ссылок. Поэтому надо быть особо внимательным при взаимодействии с Си кодом.

Для большей безопасности рекомендуется помечать как unsafe функции, реализованные на Си. Это заставит пользователя таких функций оборачивать вызов этих функций в unsafe блок и придаст больше внимательности.