enums - 连接 Ada 枚举和 C 枚举

标签 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 片段都是正确的,但我不确定。

最佳答案

两者都不是 100% 正确。

在 C 中:

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

在 Ada 中:

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 段:

Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined, but shall be capable of representing the values of all the members of the enumeration.

因此 C 类型 option_type 可以窄到 1 个字节,也可以宽到支持的最宽整数类型(通常为 8 个字节),并且它可以是有符号的或无符号的。 C 将枚举常量的值限制在 int 类型的范围内,但这并不意味着该类型本身与 int 兼容无符号整型

如果您了解正在使用的特定 C 编译器的特性(短语“实现定义”意味着必须记录这些特性),那么您可以依赖这些特性——但您的代码将不可携带。

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

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

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

关于enums - 连接 Ada 枚举和 C 枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25353190/

相关文章:

c - 在 C 中指定枚举类型的大小

java - 从不同值转换为枚举值

vim - 尝试从标签文件打开引用时,如何告诉 vim 搜索某个目录(以及当前目录)?

abstract-class - 如何在 Ada 中对抽象类进行 unchecked_deallocation?

python - 为什么 datetime.strptime 在这个简单的例子中不起作用?

C++ 显式函数签名

java - 为什么这个枚举代码是对静态字段的非法引用?

overloading - 如何在不创建递归函数的情况下重载 Ada 中的 '=' 运算符?

android - 如何使用 Kotlin 将 ByteArray 转换为 Int?

swift - 枚举函数内的错误