Избегайте предупреждающего 8-битного типа возвращаемого значения Ada Boolean, используйте Char

Я работаю над очисткой предупреждений от педантичного кода, и мы рассматриваем предупреждения как ошибки. У меня есть код интерфейса между 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++ позволяет работать с указателями и адресами памяти, что требует осторожности при программировании.


1
64
1

Ответ:

Решено

При таком подходе возникает ряд проблем. Во-первых, ваша функция 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.

Это должно работать правильно, устранять ваши предупреждения и обеспечивать некоторую защиту от изменений компилятора.