连接Ada枚举和C枚举

时间:2014-08-17 20:09:21

标签: enums ada type-conversion

让C代码定义:

typedef enum { A=1, B=2 } option_type;

void f(option_type option);

我们也有Ada代码:

type Option_Type is (A, B);
for Option_Type'Size use Interfaces.C.int'Size;
for Option_Type use (A=>1, B=>2);

X: Option_Type := A;

以下哪个代码是正确的(相应的RM)?

- 第一个代码

declare
   procedure F (Option: Option_Type)
      with Import, Convention=>C, External_Name=>"f";
begin
   F(X);
end;

- 第二个代码

declare
   procedure F (Option: Interfaces.C.unsigned)
      with Import, Convention=>C, External_Name=>"f";
   function Conv is new Ada.Unchecked_Conversion(Option_Type, Interfaces.C.unsigned);
begin
   F(Conv(X));
end;

我认为第一和第二个Ada片段都是正确的,但我不确定。

1 个答案:

答案 0 :(得分:4)

两者都不是100%正确。

在C:

typedef enum { A=1, B=2 } option_type;

在阿达:

type Option_Type is (A, B);
for Option_Type'Size use Interfaces.C.int'Size;
for Option_Type use (A=>1, B=>2);

Ada代码假定C类型option_type与C int具有相同的大小。您的第二个代码段假定它与C unsigned int具有相同的表示形式。

C标准都不支持这两种假设。

引用N1570草案,第6.7.2.2节,第4段:

  

每个枚举类型都应与 char 兼容   整数类型或无符号整数类型。类型的选择是   实现定义,但应能够代表   枚举的所有成员的值。

因此C类型option_type可以窄至1字节或宽度与最广泛支持的整数类型(通常为8字节),并且可以是有符号或无符号。 C将枚举常量的值限制为int类型的范围,但这并不意味着类型本身与int - 或与unsigned int兼容。< / p>

如果您了解您正在使用的特定C编译器的特性(短语&#34;实现定义&#34;意味着必须记录这些特征),那么您可以依赖这些特征 - 但是你的代码将是不可移植的。

我不知道任何完全可移植的方式来定义与给定C枚举类型兼容的Ada类型。 (我已经离开阿达很长一段时间了,所以我可能会错过一些东西。)

我能想到的唯一可移植方法是编写一个C包装函数,该函数接受指定整数类型的参数并调用f()。然后,由C编译器处理从整数类型到option_type的转换,并且包装器向Ada公开具有已知类型的参数的函数。

void f_wrapper(int option) {
    f(option); /* the conversion from int to option_type is implicit */
}