Интерфейс Ада с асинхронным интерфейсом в C ++ - PullRequest
3 голосов
/ 19 октября 2011

У меня есть задача по разработке нового интерфейса для распределенного приложения (несколько процессов, выполняющихся на одном компьютере, но не распределенных физически - пока), который состоит из множества модулей графической панели, написанных на C ++ / OpenGL, и одного модуля, написанного на Ada.

Модули обмениваются информацией о форме параметров (части скалярной неструктурированной информации, например: целые, строки, числа с плавающей запятой и т. Д.) Я намереваюсь спроектировать асинхронный компонент на основе сокетов (который я в дальнейшем буду называть «Интерфейсный компонент» или IC), который будет связан каждым модулем на основе библиотеки Boost :: Asio с двумя простыми «клиентскими» примитивами:

Put([ParameterName], [DestinationModule], [Payload], [Type])
Get([ParameterName], [Sourcemodule], [Payload])

ParameterName : обозначает уникальное имя параметра
DestinationModule / SourceModule : адрес модуля в системе
Полезная нагрузка : фактические данные
Тип : строка или значение, определяющее тип передаваемого параметра

Каждый из этих примитивов обрабатывается на стороне сервера двумя соответствующими функциями (на IC):

//No function parameters shown here as I don't know
//exactly how I'm going to do this
ProcessPutRequest()
ProcessGetRequest()

Поскольку обработка входящих команд будет начата IC, я намерен использовать обработчики функций, которые будут переданы вышеприведенным функциям. Таким образом, каждый программист, ответственный за каждый модуль, может обрабатывать входящие команды и выполнять необходимые преобразования типов в своем собственном коде.

Вопрос в том ... возможно ли это в Аде? Я знаю, что можно импортировать функции в C ++ и вызывать их из программ Ada. Btu можно ли передать обработчики функций из Ada в компонент C ++?

(дополнительный вопрос: есть ли у вас какие-либо предложения относительно лучшего способа реализации этого интерфейса?)

Ответы [ 5 ]

5 голосов
/ 19 октября 2011

Кодирование коммуникаций на основе сокетов является простым на обоих языках, особенно для интерфейса, который должен передавать только скалярные значения.

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

3 голосов
/ 20 октября 2011

Что касается связывания Ada с кодом c ++, в gcc есть переключатель, который создает заголовки ada из файлов .h & .cpp & .c: -fdump-ada-spec и есть инструкция с предостережения здесь .

Мое предостережение: я им не пользовался, просто знаю об этом.

3 голосов
/ 20 октября 2011

Не уверен, что семантика Get().Это ждет новых данных?вернуть последние полученные данные?(в каком случае, что произойдет, если данные еще не получены?)

Принимая схему обратного вызова и Ada 2005, вы могли бы для начала рассмотреть такую ​​спецификацию, как

generic
   type T is private;
package Interfacing is
   --  'put' not shown
   type Receiver is not null access procedure (Value : T);
   pragma Convention (C, Receiver);
   procedure Register
     (Parameter_Name : String;
      From_Module : String;
      To_Be_Received_By : Receiver);
end Interfacing;

Iм, если предположить, что IC организует маршаллинг и список зарегистрированных обратных вызовов.

Один момент, который следует опасаться: в этой схеме процедура Receiver вызывается в контексте чужого (не Ada) потока, которыйможет вызвать проблемы с поддержкой задач в среде выполнения Ada.Предполагая, что вы используете GNAT, вы должны посмотреть на GNAT.Threads (файл g-thread.ads во время выполнения).Вам необходимо как можно быстрее зарегистрировать поток, например, перед выполнением любых операций String, таких как catenation.

3 голосов
/ 19 октября 2011

Я бы не рекомендовал создавать интерфейс, который пытается объединить языки, используя, по сути, интерфейс RPC с обратными вызовами. Это будет очень сложно и может плохо взаимодействовать с механизмом задач Ады.

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

После того, как вы получите надежный интерфейс для передачи сообщений, вы можете создавать все, что вам нравится. Но главное в том, что вам не нужно создавать что-то, что вызывает «на» другом языке.

1 голос
/ 20 октября 2011

В целом, C ++ не очень хорошо работает с другими языками. Возможно, вам придется указать обеим сторонам использовать соглашение о вызовах C, которое обычно недоступно для нестатических функций-членов.

Так что любую изящную гинмастику класса, которую вы хотите сделать с Boost, вероятно, придется перевести в простой интерфейс C-ish для общения с внешним миром (в данном случае, вашим кодом Ады).

Для таких вещей есть своего рода «шаблон». У него, возможно, даже есть имя, но я не шаблонный парень, поэтому я его не знаю. То, что вы делаете, это обеспечивает статическую функцию-член, которая принимает указатель на класс в качестве параметра и внутренне вызывает себя через этот указатель класса. Затем вы делаете эту статическую функцию-член (и указатель this, который вы хотите использовать для нее) доступной для вызова внешнего (не C ++) кода. Я использую это все время, чтобы дать оператору "callback" подпрограммы C ++ - подобные интерфейсы.

class callback {
    void register () {
       // Register the callback. This usually involves somehow pointing the 
       // other side to our static do_it() routine and passing it our 
       // current "this" pointer.
    };

    void do_it(); // The member function we want callable from outside C++

    static extern "C" void do_it (callback * instance) {
        instance->do_it();
    }
};
...