Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将Ada字符串转换为C Void*_C_String_Pointers_Ada - Fatal编程技术网

将Ada字符串转换为C Void*

将Ada字符串转换为C Void*,c,string,pointers,ada,C,String,Pointers,Ada,将AdaString强制转换为System.address的好方法是什么,这相当于将char*强制转换为C中的void* 我正在连接一个C库。C类型具有类型为void*的属性,库的用户通常将C字符串指向的地址指定为该值。例如: struct my_type { void* value; }; int main() { my_type t; t.value = "banana"; } 如何从Ada字符串开始,在Ada中实现等效 我目前正在使用这种技术,但对我来说似乎有点

将Ada
String
强制转换为
System.address
的好方法是什么,这相当于将
char*
强制转换为C中的
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。

您在评论中提到您使用的是
void*
“因为它应该能够获取任何内容的地址,而不仅仅是字符串。”

因此,我们必须问通用指针如何转换为Ada,特别是如何利用类型和子类型特性。我认为,在这方面,“任何事情”都不能普遍解决;也就是说,如果您想保持构造的“灵活性”,就必须牺牲Ada为其类型系统提供的优势。此外,我认为,按现状呈现,它通常不可能可靠地用于“任何东西”

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

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


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

Type Data\u Type是接口的数组(正范围)。无符号\u 8;
对于数据类型“组件大小”使用8;
函数一些_数据(Stream:notnull访问Ada.Streams.Root_Stream_Type'Class;
长度:正)返回数据类型为
开始
返回结果:数据类型(1..Length)do
对于结果范围循环中的索引
接口。无符号_8'Read(流、结果(索引));
端环;
末端返回;
结束一些数据;

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

您应该查看包含type
chars\u ptr
的包
Interfaces.C.Strings
。导入的C函数应该使用chars_ptr类型而不是void*。此外,请查看此处建议的解决方案:该类型的
void*
成员是
void*
,因为它应该能够获取任何内容的地址;不仅仅是一根绳子。这就是为什么
g++
为它生成了Ada规范并使用了
System.Address
。我发现这项技术目前正在发挥作用。也许是声音?我猜你只想把它用在字符串上,在这种情况下,你可以修改它,使它更易于阅读,代码更少。但是是的,
System.Address
应该可以正常工作。
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;