我的任务是为分布式应用程序设计一个新接口(在一台计算机上运行的多个进程,而不是物理上分布的),它由许多用C ++ / OpenGL编写的图形面板模块和一个用阿达。
模块共享有关参数形式的信息(标量非结构化信息,例如:整数,字符串,浮点数等)。我打算设计一个基于异步套接字的组件(我将其称之为“接口组件”或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启动,所以我打算使用将传递给上述函数的函数处理程序。这样,每个模块负责的每个程序员都可以处理传入的命令,并在自己的代码上执行必要的类型转换。
问题是......这在Ada可能吗?我知道可以用C ++导入函数并从Ada程序调用它btu是否可以将函数处理程序从Ada传递给C ++组件?
(一个问题是:你有什么建议更好地实现这个界面吗?)
答案 0 :(得分:5)
在两种语言中编写基于套接字的通信都很简单,特别是对于只需要传递标量值的接口。
为模块创建单独的,与语言相关的组件远比尝试使用这种混合语言接口和链接工作更容易,更快捷。不要误解我,可以这样做,但我需要一个令人信服的理由让我这样做,而不是编写单独的,简单的套接字数据处理接口。
答案 1 :(得分:3)
我不建议构建一个尝试使用本质上使用RPC接口和回调来组合语言的接口。这将非常复杂,并且可能与Ada的任务机制发生严重冲突。
相反,设计一种将消息从一个组件传递到另一个组件的方法。例如,您可以通过套接字执行此操作。消息可以是该级别的任何合理大小的数据块。然后,在该工具的顶部,在C ++和Ada中实现代码,这些代码可以以适合每种语言的方式打包和解压缩有用的消息。
一旦你拥有一个强大的消息传递界面,你就可以构建你喜欢的任何东西。但关键是,你不需要构建任何称为“进入”另一种语言的东西。
答案 2 :(得分:3)
不确定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将组织编组和已注册的回调列表。
需要注意的一点是:在此方案中,在外部(非Ada)线程的上下文中调用Receiver过程,这可能会导致Ada运行时的任务支持问题。假设您正在使用GNAT,您应该查看GNAT.Threads
(运行时中的文件g-thread.ads
)。您需要尽快注册线程,例如在执行任何String
操作之前,例如catenation。
答案 3 :(得分:3)
关于将Ada与c ++代码相关联,gcc中有一个开关,用于创建来自.h&的ada标题。 .cpp& .c文件:-fdump-ada-spec并且有一个警告here。
我的警告:我没有用它,只知道它。
答案 4 :(得分:1)
通常,C ++与其他语言不兼容。您可能必须告诉双方都使用C
调用约定,该约定通常不适用于非静态成员函数。
因此,无论你想用Boost做什么漂亮的类动物,都可能不得不愚蠢到一个简单的C-ish界面来与外界交流(在这种情况下,你的Ada代码)。
有一种“模式”可用于做这样的事情。它甚至可能有一个名字,但我不是模范人,所以我不知道。你所做的是提供一个静态成员函数,它将一个指向类的指针作为参数,并在内部通过该类指针调用自身。然后,您可以为要调用的外部(非C ++)代码创建静态成员函数(以及要用于它的this
指针)。我一直使用它来给操作系统“回调”例程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();
}
};