Как получить сообщение об исключении Ada при отлове из обработчика C ++? - PullRequest
0 голосов
/ 21 мая 2018

Используя GNAT Ada и Gnu C ++, я связываю кусок кода Ada с оболочкой c ++ и хотел бы правильно перехватывать исключения Ada при выполнении этого (глупого) кода:

with ada.text_io;

package body ada_throw is

   procedure ada_throw is
   begin
      ada.text_io.put_line ("hello");
      raise program_error;
   end ada_throw;       

end ada_throw;

соответствующий код спецификации:

package ada_throw is

   procedure ada_throw;
   pragma export (convention => C, entity => ada_throw, external_name => "ada_throw");

end ada_throw;

Когда я делаю это на стороне C ++:

#include <iostream>

extern "C"
{
  void ada_throw();
  void adainit();
}

int main()
{
  adainit();
  ada_throw();
  std::cout << "end of program" << std::endl;
  return 0;
}

Я получаю это:

hello

raised PROGRAM_ERROR : ada_throw.adb:8 explicit raise

Итак, механизм исключенияработает, я не получаю последний отпечаток моей программы на C ++ и код возврата не равен нулю.

Теперь я хочу перехватить исключение.Если я использую catch(...), это работает, но я больше не могу получить явное сообщение об ошибке, поэтому я попробовал это:

#include <iostream>
#include <cxxabi.h>
extern "C"
{
  void ada_throw();
  void adainit();
}

int main()
{
  adainit();

  try
  {
    ada_throw();
  }
  catch (abi::__foreign_exception const &e)
  {
    std::cout << "exception" << std::endl;        
  }

  std::cout << "end of program" << std::endl;
  return 0;
}

, это работает правильно, я получаю:

hello
exception
end of program

Единственная загвоздка в том, что abi::__foreign_exception не имеет what() метода, поэтому я не могу получить содержательное сообщение об ошибке.

И отладка программы для попытки взлома e такжетупик, поскольку это просто нулевой указатель с правильным типом:

(gdb) p &e
$2 = (const __cxxabiv1::__foreign_exception *) 0x0

Есть ли способ получить его из C ++?

Ответы [ 2 ]

0 голосов
/ 21 мая 2018

В зависимости от того, что вы хотите сделать с исключением в мире C ++, может быть проще / чище написать оболочку в Ada, которая вызывает ada_throw и обрабатывает любое исключение.Затем просто вызовите эту оболочку из C ++.

Если код C ++ должен увидеть исключение и знать, что происходит, оболочка может предоставить метод what(), похожий на другой, и повторно вызвать то же самое или новое (custom) исключение.

0 голосов
/ 21 мая 2018

В Ada вы можете получить информацию о возникновении исключения, используя функции Ada.Exceptions.Exception_Name и Ada.Exceptions.Exception_Message, которые являются частью стандартной библиотеки.Один из вариантов - обеспечить тонкую привязку к этим двум функциям и вызывать их, когда вам нужна информация об исключении.(Точно, как сопоставить abi::__foreign_exception с Ada.Exceptions.Exception_ID оставлено в качестве упражнения для читателя.)

Другой вариант - сделать явным для компилятора Ada, что вы пишете C ++ с другой стороны, ииспользуйте CPlusPlus вместо C в качестве соглашения об экспорте.Это может заставить компилятор предоставлять исключения, которые понимает C ++.

Это только частичный ответ, так как я очень плохо разбираюсь в C ++, но я надеюсь, что он может помочь вам в правильном направлении.

...