【问题标题】:Converting Ada String to C Void*将 Ada 字符串转换为 C Void*
【发布时间】:2012-02-13 02:59:08
【问题描述】:

有什么好方法可以将 Ada String“转换”为 System.Adress,这相当于在 C 中将 char* 转换为 void*

我正在连接哪个 C 库。 C 类型具有void* 类型的属性,并且库的用户通常将 C 字符串指向的地址分配为该值。例如:

struct my_type {
    void* value;
};

int main() {
    my_type t;
    t.value = "banana";
}

如何在 Ada 中实现等效,从 Ada 字符串开始?

我目前正在使用这种技术,但对我来说似乎很可疑。

declare
    str : constant String := "banana";
    data : constant char_array := To_C(str);
    mine : my_type;
begin
    mine.value := data(data'First)'Address;
end;

我可以接受任何解决方案,即使是 Ada 2012。

【问题讨论】:

  • 你应该看看包Interfaces.C.Strings,它包含一个类型chars_ptr。您导入的 C 函数应使用 chars_ptr 类型而不是 void*。
  • 另外,请在此处查看建议的解决方案:en.wikibooks.org/wiki/Ada_Programming/Types/…
  • 该类型的void*成员是void*,因为它应该能够获取任何地址;不仅仅是一个字符串。这就是g++ 为其生成 Ada 规范并使用System.Address 的原因。我发现目前这项技术正在发挥作用。也许它是健全的?
  • 好吧,我猜你只想将它用于字符串,在这种情况下,你可以更改它以提高可读性并减少代码。但是,是的,System.Address 应该可以正常工作。

标签: c string pointers ada


【解决方案1】:

您在评论中提到您正在使用void*“因为它应该能够获取任何地址;不仅仅是一个字符串。”

那么,人们不得不问,通用指针是如何转化为 Ada 的,尤其是如何利用打字和子打字功能。我认为,在这种情况下,“任何事情”一般都无法解决;也就是说,如果你想保持结构的“灵活性”,你必须牺牲 Ada 提供的类型系统的优势。此外,我认为按原样呈现,通常不可能可靠地用于“任何事情”。

我这样说是因为没有任何方法可以确定包含的“任何东西”的长度。如果它是一个字符串,那么长度是从指向的地址开始,连续计数,直到第一个 NUL 字符(ASCII 0)。但是,如果它不是字符串,则没有确定长度的方法(我们怎么知道数组 [1,2,3] 或 OBJECT 的长度/大小)......所以我们甚至没有方法来确定“任何东西”的长度。

确定长度是编写稳定/安全代码的一个重要因素,因为如果不这样做,就会导致缓冲区溢出。


但是,暂且不说,如果您可以提供有关数据的一些信息,无论是通过参数还是更改my_struct,那么我们可以使用该信息来构建更好的类型转换。 (一般来说,关于类型的信息越多越好,因为您可以用以前无法做到的方式检查数据的有效性;或者更好的是,让编译器为您检查。)

Type Data_Type is Array( Positive Range <> ) of Interfaces.Unsigned_8;
  For Data_Type'Component_Size Use 8;


Function Some_Data( Stream : not null access Ada.Streams.Root_Stream_Type'Class; 
                    Length : In Positive ) Return Data_Type is
  begin
     Return Result : Data_Type(1..Length) do
        For Index in Result'Range loop
           Interfaces.Unsigned_8'Read(Stream, Result(Index));
        end Loop;
     End Return;
  end Some_Data;

您可以使用上述方法生成一个 8 位无符号整数数组,该数组将包含流中的数据。它概述了在一般情况下您必须做的事情,但由于您正在使用 C-imports,您可以做的是稍微修改它,以便 a) 有一个 Temp 变量,它是一个类似 @ 的数组987654325@ 但使用For Temp'Address Use [...] 将其覆盖在 my_type.value 上,然后使用 for 循环将其复制出来。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-15
    • 2019-05-09
    • 1970-01-01
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    • 2011-02-03
    • 2020-10-24
    相关资源
    最近更新 更多