【问题标题】:Ada to C++: Pass an unsigned 64-bit valueAda 到 C++:传递一个无符号的 64 位值
【发布时间】:2012-09-12 08:32:35
【问题描述】:

我需要将 2 条数据从 Ada 程序传递给一些 C++ 代码进行处理。

  • 数据 - 双倍。
  • 时间 - 无符号 64 位。

我能够使用 Long_Float(C++ 中的双精度)和 Integer(C++ 中的 int,但显然不是 64 位)在 Ada 中创建一个与我的 C++ 方法一起使用的过程。 我使用了以下代码(代码不在我身上,因此语法可能略有偏差):

procedure send_data (this : in hidden_ptr; data : in Long_Float; time : in Integer);
pragma import (CPP, send_data, "MyClass::sendData");

现在它正在工作,我正在尝试将时间扩展到完整的 64 位,理想情况下希望在 C++ 端有一个 unsigned long long。我在 Ada 中没有看到任何匹配的类型,所以我创建了自己的类型:

type U64 is mod 2 ** 64;

当将该类型与我的 send_data 方法一起使用时,我收到一条错误消息,指出无法将该类型映射到 C++ 类型(类似这些,我再次没有代码或确切的错误短语)。

有没有办法将 Ada 中的用户定义类型传递给 C++?也许 Ada 中还有另一种类型可以用作无符号 64 位值?如果这样更容易,有没有办法将我的 U64 类型的地址作为参数传递给 C++ 方法?我正在使用green hills adamulti compiler v3.5(对ada来说非常新,不确定该信息是否有帮助)。示例将不胜感激!

【问题讨论】:

  • mod 2 ** 64 应该是正确的。当我使用带有 GNAT 的类型编译您的示例时,它不会抱怨。也许您的 Ada 编译器不认为 C++(或它所针对的 C++ 编译器)支持 64 位无符号类型;标准 C++ 直到 2011 年 ISO 标准才获得 unsigned long long
  • @KeithThompson - 呸!让你的这些优秀的 cmets 回答 Keith,所以我的支持是有意义的,我可以适当地评论他们,如果他们最终成为答案,他们可以被接受。
  • 您可以尝试添加pragma Convention (CPP, U64);
  • 您的时间实际上是一个字段还是包含秒和毫秒字段的记录结构?如果是这样,您可以轻松地将其拆分为 2 个参数...
  • 而不是unsigned long long,在不同的实现中可能有不同的大小,试试std::uint64_t

标签: c++ interface ada


【解决方案1】:
Put_Line("First = " & Interfaces.C.long'Image(Interfaces.C.long'First));
Put_Line("Last = " & Interfaces.C.long'Image(Interfaces.C.long'Last));

结果:

First = -9223372036854775808
Last =  9223372036854775807

【讨论】:

  • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
  • 我不认识 Ada,但是如果您尝试使用 C 的 long 类型,那么在 32 位系统上会出现问题。要保证至少 64 位,您必须改用 long long
【解决方案2】:

作为@KeithThompson 评论/答案的附录...

Ada官方支持的C接口类型在Interfaces.C,里面没有超长的int和unsigned(2005版本的,2012版本正式了吗?)。

你做了正确的事情来解决它。如果您的编译器不支持这一点,则必须采取更严厉的措施。

首先要尝试的是通过引用传递 64 位 int。不过,这将需要在 C 端进行更改。

我知道 C/C++ TIME 结构往往是 64 位值,定义为联合结构。所以你可以做的是定义一个 Ada 记录来模仿其中一个 C 结构,确保它以 C 的方式布局(例如:使用记录表示和大小子句),然后使该对象成为你导入的例程所使用的它的参数。

之后,您将不得不使用讨厌的参数技巧。例如,您可以尝试将参数的 Ada 导入一侧更改为 64 位浮点数,将实际参数 unchecked_converting 转换为 64 位浮点数,然后尝试以这种方式传递它。问题在于,许多 CPU 的传递在与整数不同的寄存器中浮动。所以这可能行不通,而且如果行得通,它肯定是不可移植的。

如果您弄清楚编译器的 CPP 调用约定是如何工作的,那么可能还有其他方法可以伪造它。例如,如果它使用两个相邻的 32 位寄存器来传递 64 位整数,您可以将您的 Ada 64 位整数拆分为两个,并在 Ada 端将其传递给两个参数。如果它通过引用传递 64 位值,您可以告诉 Ada 方您正在传递指向 U64 的指针。同样,这些解决方案不会是可移植的,但它们会让你继续前进。

【讨论】:

  • 感谢 KeithThompson 和 T.E.D. 的建议。我尝试创建一个“U64_ptr 类型是访问 U64”并将 U64_ptr 作为指针而不是 U64 类型作为值传递。我收到了同样的错误,没有兼容的 C++ 类型映射到 U64。我还尝试将 unchecked_conversion 转换为 long_float,将其传递给 C++ 端的 double 并将其转换为 unsigned long long 并收到一些时髦的值(不是我所期望的,没有进一步调查)。我会在可能的情况下继续使用它,并回复我能找到的更多信息,再次感谢!
  • @Xeelot - “Funky values”通常表示一侧比另一侧取消引用更多。
  • @Xeelot -"Funky Values" 你确定你没有跨越大/小端边界吗?
  • @NWS 很好的建议,但我检查了这些位,我认为这不是问题所在。我与团队讨论过,我们决定采用简单的方法并传递 2 个 32 位值。只是在 C++ 端做了一个方法,将它们重新组合成一个 64 位整数,然后调用我们最初想要的方法。讨厌放弃这样一个坚实的问题,但截止日期不是我的朋友。再次感谢大家的帮助!
猜你喜欢
  • 2011-01-17
  • 2012-02-11
  • 1970-01-01
  • 1970-01-01
  • 2022-01-13
  • 1970-01-01
  • 2018-11-05
  • 2015-05-02
  • 1970-01-01
相关资源
最近更新 更多