首页 > 解决方案 > 在 ada 中使用静态库中的包

问题描述

我想使用位于静态库中的包中的类型和服务。

所以,在我的主体 main.adb 中,我放了一个

with Services.A;

Service.A 位于外部库(services.a)中,因此我需要在编译过程后链接该库。

我添加了标志-L/path/of/dir/containing/my/lib-lservices

但是由于类型的声明在 lib 内部并且编译器需要符号,所以我必须包含来自 services.ads 的规范(.ads)。

我看到了多种方法来做到这一点,但我的项目没有任何效果。

我尝试添加标志-I/path/to/ads但没有成功。

如果我在我的 gpr 文件中将规范添加到 Sources_Dirs,它会告诉我单元“Services.A”不能属于多个项目。

是否有任何官方方法可以从 ada 的外部静态库中包含 C 中的标头等规范?

标签: compiler-errorsada

解决方案


这里有一些东西让你开始。我希望它能给你一个好的方向。

当您将库用于 GPR 时,我知道 3 种情况。请记住,这不是一个完整的答案,肯定存在更多案例,我可能会忘记一些事情。该主题存在陷阱,因此您应该深入研究互联网、AdaCore/GNAT 文档和 stackoverflow,因为该主题经常被提出。根据您拥有/生成的库的类型以及一些特定的编译/构建/链接选项,此处可能不会涵盖某些上述陷阱。

前言:当你包含一个静态库时,它的唯一文件名不会告诉你任何有用的信息来调用它包含的代码。所以如果静态库是“serivices.a”,它只是一个文件名和扩展名。with Services.A不足以调用代码。

情况1

您可以访问my_lib.gpr生成库的 GPR,它是用 Ada 编写的。只需包含 GPR,在您的代码中您将只被允许访问with公开的接口。(它对应于 Simon Wright 关于with "services.gpr";GPR 中的评论)

  • 如果my_lib.gpr产生了一个静态库,那就没什么可做的了!GPR 为您做必要的事情(构建/链接)。
  • 如果 lib 是动态的 (dll),则需要在执行时在 OS 搜索路径中找到该 dll(在可执行文件旁边,或在路径环境变量中)

案例2

您可以访问my_lib.gpr生成库的 GPR,它是用另一种语言编写的。

  • 建立图书馆
  • my_lib_install.gpr定义另一个包含库接口声明(.ads文件)的GPR 。如果文件不存在,请参阅案例 3
  • 将该 GPR 引用到您自己的 GPR 项目中
  • 您现在可以使用.ads代码文件中定义的方法/类型。通常.ads包含pragma Import(...)约定声明。它们被定义一次,所以没有unit "Services.A" cannot belongs to several projects错误消息。

或者您可以直接将库接口声明(.ads文件)包含到您的项目中。

  • 如果my_lib.gpr生成静态库,则应包含适当的链接指令以使用 .a 文件。
  • 如果 lib 是动态的 (dll),则需要在执行时在 OS 搜索路径中找到该 dll(在可执行文件旁边,或在路径环境变量中)

案例3

该库my_lib是一个 COTS,它是用另一种语言编写的。它应该与接口定义一起交付。

通常的方法是编写.ads与提供的合同定义相对应的文件。类型和方法应使用与pragma Import(...)库构建方式相对应的某种约定进行标记(Ada 约定,C 约定,参见ARM此 wiki

通常,接口契约是一个.h文件(大多数库都是使用 C 约定生成的)。因此,您可以使用 AdaInterfaces.c专为此设计的软件包。在通过 C 约定将 Ada 与 Java 连接的示例中给出了与 C 连接的示例)。主要区别在于您将不得不pragma Import而不是pragma Export This should anwser to:

是否有任何官方方法可以从 ada 的外部静态库中包含 C 中的标头等规范?

您可以直接将此.ads文件包含到您的源中,也可以编写自己的 GPR 来进行如开头所述的托管。它是由你决定。

最后一句话,如果你的库是用 Ada 语言编码的,你可以看看关于elaboration、 'initialize' 和 'finalize' 符号的文档。


推荐阅读