Ada:pragma Pure / Remote_Types和系统类型

4
我正在编写一个需要分发的Ada应用程序,我尝试使用DSA来完成这个任务,但是我发现在"允许"和"不允许"使用的方面存在很大的限制。
由于代码相当复杂,而且这只是一个通用问题,所以我不会发布源代码,我只想得到一些关于我的错误理解的指示,请耐心指正。
我的问题是:我想用pragma Remote_Call_Interface标记一个过程,以便可以远程调用它。然而,一旦我添加了该pragma,由于该过程包含了项目中未被归类为PureRemote_Types的其他包,编译就会出错。
因此,我尝试将我需要的包标记为PureRemote_Types(根据它们是否具有状态),但这反过来又进一步破坏了编译,因为事实证明,你甚至不能在Pure/Remote_Types包中使用基本的系统类型,例如:你不能使用Vector, 你不能使用Unbounded_String, 你不能使用Map等等......整个程序崩溃了,因为我不能再使用构建它的数据结构了!
有没有什么方法可以解决这个问题?或者如果我想分发我的应用程序,我必须严格限制自己只使用最基本的类型,如整数和布尔值等?我不明白我是否受到了语言的限制,还是我只是做错了(不幸的是,我找到的DSA教程都非常模糊,如果有人有好的教程,请随意链接!)
编辑: 在ajb的回答之后,让我具体说明一下我的烦恼: 在我想用pragma Remote_Call_Interface标记的包中,我试图"with"一些非pure/remote_types的包,但它仅在本地使用那些包中的类型,它没有包含任何接受这些类型作为参数或返回这些类型的函数。这就是我的困扰所在: 由于这些类型不需要在网络上传输,为什么我不能使用它们呢?我只在本地使用它们......我不理解这一点,这就是我试图使这些类型成为Pure/Remote_Types的原因,但现在我已经阅读了ajb的解释(即:Remote_Types用于使这些类型的对象可以在网络上传输),我更加困惑为什么如果我只在本地使用它们,为什么我不能使用它们。

根据您的编辑,我已经修改了我的答案。 - ajb
1个回答

3

我不是Ada分布式编程的专家,但这是我所知道(或认为我知道)的:

Ada参考手册注释,第E.2.3节说:“远程调用接口库单元的限制旨在确保远程调用中实际参数的值可以在两个活动分区之间有意义地发送。”例如,如果记录类型具有字段是访问类型,则不能盲目将其从一个分区发送到另一个分区,因为被调用的分区将无法访问指针所指向的内存。(Unbounded_StringMapVector使用访问类型作为内部的一部分实现。)所有用作参数或返回类型的类型必须支持“外部流”,这意味着必须有一种方法将该类型转换为字节流并从中转换,以便可以通过套接字传输参数值。如果您有一个带有访问类型的记录,但提供了'Read'Write属性,以便可以将该类型写入字节流中并从中读取而不传输任何实际指针,则可以将记录类型放入Remote_Types包中。

我不确定你的问题具体是什么:你想把某些类型作为参数传递给远程调用,但无法实现;还是有些类型只想在应用程序的其他部分中使用,但却妨碍了你?
如果是后者,那么我认为解决方案是重新构造你的包,使所有的“远程类型”与非远程类型分开。
然而,如果你真的想在远程调用中传递一个Unbounded_StringMapVector,那就比较棘手了。Unbounded_String 应该支持外部流式传输,并且曾经有一个提案将 Unbounded_String 作为一个 Remote_Types 包(请参见AI05-0204),但是没有得到采纳——我不知道为什么。而MapVector会更麻烦,因为它们是通用包,必须适用于任何类型,包括那些不支持外部流式传输的类型。无论如何,这些类型都没有设置自动转换成或从字节传输以通过套接字传递。

但我认为你可以这样做:

private with Ada.Strings.Unbounded;
package Remote_Types_Package is
    pragma Remote_Types;
    type My_Unbounded_String is private;
private
    type My_Unbounded_String is record
        S : Ada.Strings.Unbounded.Unbounded_String;
    end record;
end Remote_Types_Package;
Unbounded_String包必须使用private with;请参见E.2.2(6)。 您需要提供一个函数来创建My_Unbounded_String,并为My_Unbounded_String提供流读取和写入例程,并为该类型定义'Read'Write。您应该能够通过使用Unbounded_StringReadWrite属性来编写ReadWrite属性。如果您想将Vector用作远程调用参数,则类似的事情也可以做到,尽管您可能需要自己进行更多的编组/解组工作。

再次强调,我没有尝试过这个方法,这个解决方案可能存在一些问题。

编辑:由于现在看起来问题更简单——也就是说,你有一些类型不会在分区之间传递,并且会妨碍解决方案。因此,解决方案应该更简单。您定义的任何要在分区之间通信的类型都需要在一个Remote_Types包中,比如P1。其他类型应该在另一个包中,比如P2(或多个包)。如果P1中的类型依赖于P2中的类型,您仍然可以通过让P1private with P2;并确保您拥有所需的编组和取消编组过程来使其工作。如果遇到困难,请在这里提出新问题。
我不知道为什么编程语言要求所有这些类型都必须被隔离在一个名为Remote_Types的包中,而不是只说任何在Remote_Call_Interface包中使用的类型必须只包含可流式传输的部分。可能存在一些实现问题。任何存在于Remote_Types包中的代码都必须在两个分区的程序中,这可能是限制需要链接到多个分区的代码类型的尝试。但这只是我的猜测。

很遗憾,使用private关键字仍然无法解决问题,编译器仍然会报错“无法依赖于“P2”(错误分类)”。 - Master_T
1
我现在无法完整发布它(这是为大学项目而准备的),但如果我通过了,我将很乐意上传它。 - Master_T
@Master_T -- 提醒一下,如果你的DSA程序完成了,我们希望能看到它。 - Shark8
@Shark8:非常抱歉回答晚了:D 但最终我放弃了DSA,使用SOAP实现了自己的类RPC协议。虽然不太美观,但DSA让我发疯了,直到今天我仍然对它的运作原理知之甚少。 - Master_T
@Master_T -- 我知道你的意思,GNAT对DSA的实现有点笨重(我猜测这是因为业余爱好者相对较少使用)。-- 但如果你在github或其他地方上有源代码,我仍然想看一下。 - Shark8
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接