Я работаю над очисткой предупреждений от педантичного кода, и мы рассматриваем предупреждения как ошибки. У меня есть код интерфейса между Ada и C++, который выглядит так:
Ада менеджер.объявления:
function Foo(ID_Type : in Integer) return Boolean;
pragma Import(CPP, Foo, "Foo");
С++ Адаманагер.cpp:
extern "C" bool Foo(int32_t ID)
{
return Manager::GetManager()->Bar(ID);
}
С++ Адаманагер.h:
extern "C" bool Foo(int32_t ID);
С++ менеджер.cpp:
bool Manager::Bar(int32_t ID)
{
//function body
return answer;
}
С++ менеджер.h
static bool Bar(int32_t ID);
Вывод gcc -c для manager.ads:
warning: return type of "Foo" is an 8-bit Ada Boolean
warning: use appropriate corresponding type in C (e.g. char)
У меня куча таких случаев.
Чтобы избавиться от предупреждений, мне нужно заменить все логические значения на char или какой-либо другой 8-битный тип, а затем выполнить явное преобразование типов в основном коде Ada? Почему компилятор решил, что логическое значение должно быть 8-битным?
При таком подходе возникает ряд проблем. Во-первых, ваша функция C должна быть объявлена с использованием типов C. Хотя есть стандартные заголовки, которые объявляют bool
и int32_t
, поскольку вы их не включаете, вы должны заменить их соответствующими типами C, возможно, char
и int
:
extern "C" char Foo (int ID);
Во-вторых, поскольку ваша функция объявлена как C, а не C++, вы должны импортировать ее по соглашению C, а не CPP. (Единственная причина объявления таких C-оболочек вокруг C++ состоит в том, чтобы избежать проблем прямого взаимодействия с C++.)
В-третьих, плохой идеей является взаимодействие с C с использованием неконвенционных типов C, таких как Integer и Boolean. Это может работать, но не гарантируется продолжение работы с будущими версиями компиляторов. Лучше использовать соответствующие типы из Interfaces.C.
В-четвертых, у вас нет гарантии, что возвращаемое значение будет ограничено 0 или 1, поэтому вам нужно обрабатывать его так же, как это делает C, 0 или не 0.
При всем этом ваша Ада становится
with Interfaces.C;
function Foo (ID : in Integer) return Boolean is
function Foo (ID : in Interfaces.C.int) return Interfaces.C.unsigned_char
with Import, Convention => C, External_Name => "Foo";
use type Interfaces.C.unsigned_char;
begin -- Foo
return Foo (Interfaces.C.int (ID) ) /= 0;
end Foo;
хотя вы, вероятно, захотите использовать тип, отличный от Integer, для идентификаторов на стороне Ada.
Это должно работать правильно, устранять ваши предупреждения и обеспечивать некоторую защиту от изменений компилятора.
Я предполагаю, что есть некоторые ограничения, если я могу использовать только Ada95. Например, тогда мне все равно придется использовать Pragma Import, да?
Значение, содержащееся в типе bool C++, будет равно 0 для false и 1 для true. C++ определяет тип bool как 8-битное значение без знака, которое четко отображается на тип char, определенный в пакете interfaces.c.