如何创建 ada lib.a 并链接到 C

2023-11-24

我正在尝试创建一个 ada 库并尝试了一些不同的东西。 我尝试使用 makefile 编译项目并尝试从所有 .o 文件创建一个库 这似乎没有按预期工作。 然后我询问了 adacore 支持,他们向我指出了在 ada 和 c 项目中使用 .gpr 文件的方向,并在 ada.gpr 中创建一个库。这几乎有效,但是当它尝试编译 ada 时,我得到了未定义的引用。

我尝试过的: 命令行:

ar rc libmy_lib.a *.o

当我尝试阅读库中的内容时

ld libmy_lib.a

我收到这个错误 ld:警告:找不到入口符号_start;不设置起始地址

项目文件: 我的 ada 项目文件 prj.gpr

project Prj is
for Source_Dirs use ("source1/", "source2", ....);
for Object_Dir use ".";

for Languages use ("Ada");
for Library_Name use "test";
for Library_Dir use "lib";
for Library_Interface use (
 --All my ada packages
        );

package Naming is
      for Spec_Suffix ("ada") use ".1.ada";
      for Body_Suffix ("ada") use ".2.ada";
      for Separate_Suffix use ".2.ada";
      for Dot_Replacement use ".";
   end Naming;

   package Compiler is
      for Default_Switches ("ada") use ("-v", "-g", "-gnato", "-gnatwa", "-gnatQ", "-gnat05");
   end Compiler;

   package Builder is
      for Global_Compilation_Switches ("Ada") use ("-gnat95");
   end Builder;

   package Ide is
  end Ide;

end Prj;

我的c项目文件c_main.gpr

with "prj.gpr";
project C_Main is
for Source_Dirs use ("source_c_1/", "source_c_2/");
for Languages use ("C");
for Main use ("source_c_1/main.c");
end C_Main;

当我运行命令时 gprbuild c_main.gpr

我有两个不同的错误: 首先是对一些包的未定义引用,这些包是我的 ada 代码的一部分,并且在我不知道存在的 gnat .adb 文件中。我想图书馆太破了。 其次,即使代码编译良好并运行,某些包的字段也无法找到/不存在。它给我错误,指出 ada 代码中不存在这些字段。

总而言之: 我在 3 个不同的目录中有一个 ada 项目,我想从中创建一个库。然后链接到 C 测试程序。最终我只需要提供库文件即可。命令行是最好的。我不想处理项目文件。


创建静态库有大问题libtest.a.

首先,Ada代码极有可能调用Ada运行时系统(RTS)。如果您创建静态库,您(或您的用户)将需要显式调用 Ada RTS,无论您是否使用gprbuild。所以两者都不是

gcc main_c.c -ltest

nor

gprbuild -P c_main

就足够了;你会遇到这样的失败(甚至更糟):

$ gcc main.c -Lada/lib -ltest
Undefined symbols for architecture x86_64:
  "_ada__calendar__delays__delay_for", referenced from:
      _Hello in libtest.a(hello.o)
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status

其次,Ada 代码可能(将会!)需要在程序启动时进行详细阐述。什么时候gprbuild创建它添加功能的库testinit(),你的 C 代码must在调用库的任何接口之前调用,并且testfinal()在使用完该库后被调用(大多数人不会打扰)。

解决第一个问题的方法是创建一个动态库(.dll在 Windows 上,.so在 Linux 和其他 Unix 系统上,.dylib在 Mac OS X 上)。要做到这一点,你说for Library_Kind use "dynamic";. (请注意,虽然动态库知道它需要哪些其他库,但它可能不知道在哪里可以找到它们,因此您必须将它们安排在加载程序的库搜索路径上)。

解决第二个问题的方法是创建 AdaCore 所谓的独立动态库,并让它自动初始化。

为此,您需要添加两个属性:

  • for Library_Interface use (...);指定您希望在库外可见的单元名称列表。效果是仅包括指定单位的来源和.ali库中的文件;如果唯一的调用者来自 C,那么您可能只需要说出其中一个即可。
  • for Library_Auto_Init use "true";- 我认为这实际上是默认的。

我设置了一个小示例(在 Mac OS X 上,GNAT GPL 2014)。

子目录ada

项目文件,

library project Prj is
   for Languages use ("ada");
   for Library_Name use "test";
   for Library_Kind use "dynamic";
   for Library_Interface use ("hello");
   for Library_Auto_Init use "true";
   for Library_Src_Dir use "include";
   for Library_Dir use "lib";
   for Source_Dirs use (".");
   for Object_Dir use ".build";
end Prj;

你好,广告,

function Hello return Integer;
pragma Export (C, Hello, "Hello");

你好.adb,

with Number;
function Hello return Integer is 
begin
   delay 0.001;            -- so the tasking runtime gets called in
   return Number.Value;
end Hello;

数量.广告,

package Number is
   pragma Elaborate_Body;
   Value : Integer := 0;   -- before elaboration
end Number;

和号码.adb

package body Number is
begin
   Value := 42;            -- after elaboration
end Number;

父目录

项目文件,

with "ada/prj";
project C_Main is
   for Source_Dirs use (".");
   for Languages use ("c");
   for Main use ("main.c");
   for Exec_Dir use ".";
   for Object_Dir use ".build";
end C_Main;

和main.c

#include <stdio.h>

extern int Hello(void);

int main() {
  int hello = Hello();
  printf("Hello returned %d.\n", hello);
  return 0;
}

构建

$ gprbuild -p -P c_main
gcc -c main.c
gcc -c -fPIC number.adb
gcc -c -fPIC hello.adb
gprlib test.lexch
gnatbind -n -o b__test.adb -Ltest -a /Users/simon/tmp/crychair/ada/.build/number.ali ...
gcc -c -x ada -gnatA -gnatws b__test.adb -o b__test.o ...
gcc -dynamiclib -shared-libgcc -o /Users/simon/tmp/crychair/ada/lib/libtest.dylib ... /Users/simon/tmp/crychair/ada/.build/number.o ...
ar cr libc_main.a ...
ranlib -c libc_main.a
gcc main.o -o main

和执行:

$ ./main
Hello returned 42.

要将您的库分发给另一台计算机上的 C 用户,在尚未安装 Ada 运行时的情况下,您需要打包libtest.so (or .dylib, or .dll)和所需的 Ada 共享库。

在 Unix 系统上,你可以使用以下命令找到这一点:ldd libtest.so您正在寻找libgnat*.so and libgnarl*.so。您应该在编译器的对象搜索路径中找到它们(通常是输出的“对象搜索路径”部分的最后一行)gnatls -v)。通常会有符号链接:

libgnat.so       ->      libgnat.1.so
libgnat.1.so     ->      libgnat.1.0.0.so
libgnat.1.0.0.so         (the real thing)

将共享库和符号链接放入目录中libtest.so, say product/,那么您的用户应该能够链接到

gcc main.c -o main -Lproduct -ltest

or maybe

gcc main.c -o main -Lproduct -ltest -lgnat -lgnarl

根据您的操作系统,生成的可执行文件可能无法在运行时找到共享库。

解决这个问题的一种方法是将库放在加载器已经查找过的位置,例如/usr/local/lib(在这种情况下,您不需要-Lproduct).

另一种方法是通过设置环境变量来告诉加载程序去哪里查找(LD_LIBRARY_PATH在Linux上,DYLD_LIBRARY_PATH在 Mac OS X 上)。

第三种方法是告诉链接器将路径保存在可执行文件中:

gcc main.c -o main -Lproduct -ltest -lgnat -lgnarl -Wl,-rpath,$PWD/product

可以在 Mac OS X 上运行,也可能在 Linux 上运行。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何创建 ada lib.a 并链接到 C 的相关文章

  • 检测到 NuGet 包的版本冲突

    我正在开发 ASP Net core 2 1 Web 应用程序项目 我的解决方案中有 1 个项目和 3 个其他库 它是高级架构 数据访问层 DAL 业务层 BL 公共层 CL 所以我需要添加引用来连接一些库和项目 我已经添加了CL参考我的项
  • 如果.Net Core可以在Windows上运行,为什么不能在.Net Framework中引用.Net Core DLL?

    我明白为什么 Net Framework 可能会在 Net Core IE 中导致问题 因为不存在特定于 Windows 平台的 API 但是为什么不能直接引用 Net Core 作为 Net Framework 中的库呢 如果 Net C
  • 获取两个字符串之间的公共部分c# [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我需要的是获取两个单词之间的共同部分并获取差异 例子 场景1 word1 感言 word2 Test 将返回 公共部分Test 不同之
  • 捕获 foreach 条件中抛出的异常

    我有一个foreach在 foreach 本身的条件下循环期间中断的循环 有没有办法try catch抛出异常然后继续循环的项 这将运行几次 直到异常发生然后结束 try foreach b in bees exception is in
  • 在 C++11 中省略返回类型

    我最近发现自己在 C 11 模式下的 gcc 4 5 中使用了以下宏 define RETURN x gt decltype x return x 并编写这样的函数 template
  • Guid 应包含 32 位数字和 4 个破折号

    我有一个包含 createuserwizard 控件的网站 创建帐户后 验证电子邮件及其验证 URL 将发送到用户的电子邮件地址 但是 当我进行测试运行时 单击电子邮件中的 URL 时 会出现以下错误 Guid should contain
  • try-catch 中未处理的异常

    try list from XElement e in d Descendants wix File where e Attribute Name Value Contains temp Name e Parent Parent Attri
  • 调试内存不足异常

    在修复我制作的小型 ASP NET C Web 应用程序的错误时 我遇到了 OutOfMemoryException 没有关于在哪里查看的提示 因为这是一个编译时错误 如何诊断此异常 我假设这正是内存分析发挥作用的地方 有小费吗 Thank
  • 禁用 LINQ 上下文的所有延迟加载或强制预先加载

    我有一个文档生成器 目前包含约 200 个项目的查询 但完成后可能会超过 500 个 我最近注意到一些映射表示延迟加载 这给文档生成器带来了一个问题 因为它需要根据生成的文档来访问所有这些属性 虽然我知道DataLoadOptions可以指
  • 两组点之间的最佳匹配

    I ve got two lists of points let s call them L1 P1 x1 y1 Pn xn yn and L2 P 1 x 1 y 1 P n x n y n 我的任务是找到它们点之间的最佳匹配 以最小化它
  • 用于从字符串安全转换的辅助函数

    回到 VB6 我编写了一些函数 让我在编码时无需关心字符串的 null 和 数字的 null 和 0 等之间的区别 编码时 没有什么比添加特殊情况更能降低我的工作效率了用于处理可能导致一些不相关错误的数据的代码 9999 10000 如果我
  • 在 C 中复制两个相邻字节的最快方法是什么?

    好吧 让我们从最明显的解决方案开始 memcpy Ptr const char a b 2 调用库函数的开销相当大 编译器有时不会优化它 我不会依赖编译器优化 但即使 GCC 很聪明 如果我将程序移植到带有垃圾编译器的更奇特的平台上 我也不
  • Qt - 设置不可编辑的QComboBox的显示文本

    我想将 QComboBox 的文本设置为某些自定义文本 不在 QComboBox 的列表中 而不将此文本添加为 QComboBox 的项目 此行为可以在可编辑的 QComboBox 上实现QComboBox setEditText cons
  • 从匿名类型获取值

    我有一个方法如下 public void MyMethod object obj implement 我这样称呼它 MyMethod new myparam waoww 那么我该如何实施MyMethod 获取 myparam 值 Edit
  • Silverlight Datagrid:在对列进行排序时突出显示整个列

    我的 Silverlight 应用程序中有一个 DataGrid 我想在对该列进行排序时突出显示整个列 它在概念上与上一个问题类似 Silverlight DataGrid 突出显示整列 https stackoverflow com qu
  • 如何检测 C# 中该字典键是否存在?

    我正在使用 Exchange Web 服务托管 API 和联系人数据 我有以下代码 即功能性的 但并不理想 foreach Contact c in contactList string openItemUrl https service
  • 为什么我使用google'smtp'无法发送电子邮件?

    我有以下程序使用 smtp gmail com 587 发送电子邮件 namespace TestMailServer class Program static void Main string args MailMessage mail
  • 过度使用委托对性能来说是一个坏主意吗? [复制]

    这个问题在这里已经有答案了 考虑以下代码 if IsDebuggingEnabled instance Log GetDetailedDebugInfo GetDetailedDebugInfo 可能是一个昂贵的方法 因此我们只想在调试模式
  • 如何查明CONFIG_FANOTIFY_ACCESS_PERMISSIONS是否启用?

    我想利用fanotify 7 http man7 org linux man pages man7 fanotify 7 html我遇到的问题是在某些内核上CONFIG FANOTIFY ACCESS PERMISSIONS不起作用 虽然C
  • 从类模板参数为 asm 生成唯一的字符串文字

    我有一个非常特殊的情况 我需要为类模板中声明的变量生成唯一的汇编程序名称 我需要该名称对于类模板的每个实例都是唯一的 并且我需要将其传递给asm关键字 see here https gcc gnu org onlinedocs gcc 12

随机推荐

  • 需要减少expressjs中某个路由的超时时间

    在expressjs中 有一种方法可以设置每个路由的超时限制 我有一些路线可能需要 30 45 秒才能处理 大量任务 然后是其他路线 如果花费的时间超过 5 秒 我希望它超时 我想我问是否有一种方法可以全局设置请求的超时限制 并且有没有一种
  • 有没有办法检查Python中的函数是否递归?

    我想为练习编写一个测试函数 以确保函数正确实现 所以我想知道 有没有一种方法 给定一个函数 foo 来检查它是否是递归实现的 如果它封装了一个递归函数并使用它 它也算在内 例如 def foo n def inner n more code
  • Pandas 发现交叉值中的重复项

    我有一个数据框 想要消除具有相同值但在不同列中的重复行 df pd DataFrame columns a b c d index 1 2 3 df loc 1 pd Series a x b y c e d f df loc 2 pd S
  • Pentaho 数据集成无法在新的 Mac M1 上启动

    当我尝试在 Mac bigSur M1 上运行 Pentaho Data Integration 时遇到问题 问题代码如下 I m sorry this Mac platform arm64 is not yet supported Ple
  • UIImage 和 ressizedImageWithCapInsets Swift

    我是 Swift 的 Apple 新手 我读过一篇文章Here 但不知道如何做这样的事情 或者只是简单不知道如何使用resizableImageWithCapInsets与斯威夫特 请帮我使用resizableImageWithCapIns
  • 绝对 xpath 和相对 xpath 有什么区别? Selenium 自动化测试中哪个是首选?

    绝对 xpath 和相对 xpath 有什么区别 Selenium 自动化测试中哪个是首选 我正在使用 Selenium 和 Robot 框架准备测试脚本 绝对Xpath 它使用从根元素到期望元素的完整路径 相对Xpath 您可以简单地从引
  • 如何将 Maven 站点部署到 Artifactory?

    我们是从一个非常古老的 Artifactory 已有 6 7 年历史 升级而来的 当时 由于空间限制 部分存储库不是由 Artifactory 处理 而是通过 Apache httpd 服务器通过 HTTP 提供服务 通过 Apache h
  • Lua:仅当表中尚未存在时添加到表中或删除重复项的最智能方法

    我有一张字符串表 我想要一种简单的方法来删除表中的所有重复项 所以如果表是 a b c c d e e 经过此操作后将是 a b c d e 或者 也许更好的是 有一种方法可以将元素添加到表中 但前提是该元素尚未包含在表中 我通常为此做的是
  • Haskell - 是什么让“main”独一无二?

    有了这个代码 main FilePath gt FilePath gt IO main wrPath rdPath do x lt readFile rdPath writeFile wrPath x 我收到以下错误 Couldn t ma
  • 搜索大文本文件

    我正在尝试优化大型文本文件 300 600mb 中字符串的搜索 使用我目前的方法 花费的时间太长 目前我一直在使用IndexOf搜索该字符串 但为该字符串的每一行建立索引所需的时间太长 20 秒 如何优化搜索速度 我试过了Contains
  • FOS 其余捆绑包:无法找到模板

    我得到例外 找不到模板 其他类似的问题没有帮助 奇怪的是 它工作正常 然后突然开始给我这个例外 作曲家 friendsofsymfony rest bundle 0 13 dev jms serializer bundle 0 12 dev
  • conda-forge 安全吗?

    我去conda forge下载PyPDF2 conda install c conda forge pypdf2 并收到此消息 The following packages will be UPDATED ca certificates a
  • TypeScript:仅包​​含语句的导入模块

    我有一个page a ts这将编译成page a js alert this is from page a 我有一个main ts编译成main js import pageA module page a alert this is fro
  • Python:MySQL:处理超时

    我使用Python和mySQL 查询之间有很长的延迟 结果 我收到 MySQL 连接已消失 错误 即超出了 wait timeout 这已经被讨论过 例如在优雅地处理 MySQL 已经消失 但这并没有具体回答我的问题 所以我的处理方法是 我
  • 在Android TextView中,可以插入段落吗?

    以下是我遇到的问题类型的示例 我在 pojo 中有数据 需要在文本视图中显示 该数据具有伪代码 用 p 表示每个段落 当它们显示在文本视图中时 我想以某种方式将 p 解析为段落 这可以做到吗 有什么东西可以代替 p 来在文本视图中创建一个新
  • 网站上的 Disqus SSO 集成

    我们在我们的网站中加入了 Disqus 上的 SSO 功能 按照此处的 Disqus 文档进行操作http help disqus com customer portal articles 526768和这里http help disqus
  • 没有匹配的构造函数来初始化“mapped_type”std::map 错误

    我有一个名为 Card 的类 我试图将其一些对象存储在 std map 中 卡 hpp class Card public enum ValueType NOVALUE ACE enum FaceType NOFACE CLUBS Card
  • 为什么Lua的长度(#)运算符返回意外的值?

    Lua 有 运算符来计算用作数组的表的 长度 我检查了这个运营商 我很惊讶 这是我在 Lua 5 2 3 下运行的代码 t t 0 1 t 1 2 print t 1 aha lua counts from one t 2 3 print
  • 如何在javascript中将选定的文本设置为粗体/斜体/下划线?

    我正在尝试开发一个允许用户为学校项目编写自己的笔记的网页 我的想法是让他们使用按钮将文本加粗 斜体 下划线 截至目前 这些按钮正在工作 但它们对文本区域内的所有内容进行粗体 斜体 下划线 相反 我希望它以这样的方式工作 只有它们突出显示的文
  • 如何创建 ada lib.a 并链接到 C

    我正在尝试创建一个 ada 库并尝试了一些不同的东西 我尝试使用 makefile 编译项目并尝试从所有 o 文件创建一个库 这似乎没有按预期工作 然后我询问了 adacore 支持 他们向我指出了在 ada 和 c 项目中使用 gpr 文