【问题标题】:Interfacing Ada with an asynchronous interface in C++在 C++ 中将 Ada 与异步接口连接
【发布时间】:2011-10-19 18:51:04
【问题描述】:

我的任务是为分布式应用程序(在单台计算机上运行多个进程,尚未物理分布)设计一个新界面,该应用程序由许多用 C++/OpenGL 编写的图形面板模块和一个用艾达。

模块以参数的形式共享信息(标量非结构化信息,例如:整数、字符串、浮点数等...)。我打算设计一个基于 Boost::Asio 库和两个简单​​“客户端”原语的每个模块链接的基于异步套接字的组件(我将在下文中将其称为“接口组件”或 IC):

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

ParameterName:指定唯一的参数名称
DestinationModule/SourceModule:寻址系统中的模块
有效负载:实际data
类型:标识所传递参数类型的字符串或值

这些原语中的每一个都在服务器端由两个相应的函数(在 IC 上)处理:

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

因为传入命令的处理将由 IC 启动,我打算使用将传递给上述函数的函数处理程序。这样每个模块负责的每个程序员都可以处理传入的命令并对自己的代码执行必要的类型转换。

问题是……这在 Ada 中可行吗?我知道可以在 C++ 中导入函数并从 Ada 程序中调用它 btu 是否可以将函数处理程序从 Ada 传递给 C++ 组件?

(附带的问题是:您对实现此接口的更好方法有什么建议吗?)

【问题讨论】:

  • 除了通过传入处理函数的地址可以在纯 C 语言中执行的操作之外,您所说的“函数处理程序”还有什么意思吗?您当然可以在 Ada 中编写与此类处理函数等效的函数。虽然如果 Ada 调用你的 Get() 我不明白你为什么想要?
  • 哎呀,我想我的问题应该更完整:我想使用这个接口来使我的应用程序的每个模块都能够执行客户端和服务器操作。作为服务器,模块将需要处理传入的数据。当此数据(参数或消息)到达时,由接口组件处理。问题是:如何让模块在不轮询 IC 的情况下处理传入的数据?使用处理程序的想法是调用它们,以便在消息到达 IC 时调用模块代码。

标签: c++ sockets asynchronous boost-asio ada


【解决方案1】:

在两种语言中编写基于套接字的通信都很简单,尤其是对于只需要传递标量值的接口。

为模块创建单独的适合语言的组件将比尝试使这种混合语言接口和链接正常工作更容易和更快。不要误会我的意思,这是可以做到的,但我需要一个令人信服的理由才能让我这样做,而不是编写单独的、简单的套接字数据处理接口。

【讨论】:

    【解决方案2】:

    不确定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;
    

    我假设 IC 将组织编组和注册回调列表。

    需要注意的一点:在这个方案中,Receiver 过程是在外部(非 Ada)线程的上下文中调用的,这可能会导致 Ada 运行时的任务支持出现问题。假设您使用的是 GNAT,您应该查看 GNAT.Threads(运行时中的文件 g-thread.ads)。您需要尽快注册线程,例如在执行任何String 操作(如连接)之前。

    【讨论】:

      【解决方案3】:

      我不建议构建一个尝试将语言结合起来的接口,该接口本质上是使用 RPC 接口和回调。这将非常复杂,并且可能与 Ada 的任务机制交互不良。

      相反,设计一种将消息从一个组件传递到另一个组件的方法。例如,您可以通过套接字执行此操作。消息可以是该级别的任何合理大小的数据块。然后,在该工具之上,在 C++ 和 Ada 中实现代码,以适合每种语言的方式打包和解包有用的消息。

      一旦您拥有了强大的消息传递接口,您就可以在此基础上构建任何您喜欢的东西。但关键是,您不需要构建任何“融入”其他语言的东西。

      【讨论】:

      • 嗯,你是说拥有一个统一的组件不值得麻烦连接 C++ 和 Ada 代码?请注意,我所说的 IC 旨在链接到 Ada 代码,而不是通过 RPC 调用。
      • 好吧,我想我误解了你所说的“在一台计算机上运行多个进程”。
      【解决方案4】:

      关于将 Ada 与 c++ 代码链接,gcc 中有一个开关可以从 .h 和 .cpp 和 .c 文件创建 ada 标头:-fdump-ada-spec 并且有一个带有警告的操作指南here

      我的警告:我没有使用它,只是知道它。

      【讨论】:

      • 另一个(诚然相当明显的)警告是 C++ 和 Ada 端都必须使用 gcc 编译。
      【解决方案5】:

      一般来说,C++ 不能很好地与其他语言配合使用。您可能必须告诉双方使用 C 调用约定,这通常不适用于非静态成员函数。

      因此,无论您想用 Boost 做什么漂亮的体操课,都可能必须简化为一个简单的 C 式界面才能与外界对话(在这种情况下,是您的 Ada 代码)。

      有一种“模式”可以用来做这样的事情。它甚至可能有一个名字,但我不是一个模式人,所以我不知道。您所做的是提供一个静态成员函数,该函数将指向该类的指针作为参数,并通过该类指针在内部调用自身。然后,使该静态成员函数(以及要用于它的 this 指针)可供外部(非 C++)代码调用。我一直使用它来为操作系统“回调”例程提供类似 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();
          }
      };
      

      【讨论】:

        猜你喜欢
        • 2011-03-20
        • 2014-04-19
        • 2020-11-26
        • 2015-01-15
        • 2016-08-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多