【问题标题】:Variadic function in Ada (C - Ada binding)?Ada 中的可变参数函数(C - Ada 绑定)?
【发布时间】:2016-03-05 19:50:01
【问题描述】:

我正在开发一个使用 C - Ada 语言绑定的项目。 C 中的函数将调用 Ada 端的函数。我想在 Ada 中创建一个可变参数函数,它可以接收从 C 函数发送的可变数量的参数。我还想同时发送不同类型的参数,例如 int、char、enums 等。有没有可能有这种机制?

【问题讨论】:

  • 我不知道这是否可能,Ada 的类型非常强,而可变参数函数打破了这一点。
  • 没有。对于要创建的每个呼叫配置文件,您都需要一个不同的 Ada 子程序。请参阅GNAT User Guide。 .... 等等,如果您不使用 GNAT,它可能只是可能的;询问您的编译器供应商。

标签: c variadic-templates ada variadic-functions


【解决方案1】:

即将推出的 Ada 标准 Ada 202x 计划提供对调用 C 可变参数函数的支持。

然后你就可以写了;

package C renames Interfaces.C;

procedure Printf (Format : in C.char_array)
  with Import => True, Convention => C_Variadic_1, External_Name => "printf";

【讨论】:

    【解决方案2】:

    您不能在 Ada 中创建可变参数函数。您可以通过多种方式模拟可变参数函数。

    1. Ada 允许您为函数和过程指定默认值。如果您想使用默认值,则不必总是指定默认参数的值。
    2. 您可以将一个或多个参数定义为变体记录。

    【讨论】:

    • 检查了另一种方法here
    【解决方案3】:

    不可能以可移植的方式从 Ada 调用任何 C 可变参数函数!

    其中一个原因 - 一些 ABI 使用特殊方式/寄存器来传递浮点值。这意味着 C 编译器将使用此寄存器,因为事先不知道参数是否为浮点数。 Ada 编译器不会使用这个寄存器(因为你不能在 Ada 包装函数声明中放入浮点参数)。结果,您将遇到崩溃、堆栈损坏或任何其他未定义的行为。

    特别是AMD64 ABI 指定:

    %rax - 使用可变参数传递信息 关于使用的向量寄存器的数量

    %xmm0–%xmm1 - 用于传递和返回浮动 点论据

    唯一可移植的解决方案是使用具有固定数量参数的 C 包装器,然后像往常一样绑定它。

    【讨论】:

    • 我确认帕特里克的回答。这已在 Ada 202x 中修复,并已在 GNAT 社区版 2020 中实现。
    【解决方案4】:

    您可以使用 'address 或包 System.Address_To_Access_Conversions 和 'access(或 'unchecked_access)来生成您要传递的每个项目的地址。

       type Address_Array is array (positive range <>) of System.address;
       function C_Caller(Params : Address_Array) return Integer is begin return 0; end;
       X, Y, Z, Result : Integer;
    begin
       result := C_Caller(Address_Array'(x'address, y'address, z'address));
    

    ...然后您需要编译导入实际函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多