将Ada字符串转换为C Void*
将Ada将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中实现等效 我目前正在使用这种技术,但对我来说似乎有点
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循环将其复制出来。您应该查看包含typechars\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;