我正在开发一个C-ADA绑定项目,我需要将在ADA端声明的String传递给C函数。在其中一个ADA函数中,我将有界char数组声明为:
Str_C : Interfaces.C.Char_Array(1..23) := (others => Interfaces.C.nul);
并将Char_Array_Access
类型的向量声明为:
Ptr1 : Interfaces.C.Strings.Char_Array_Access := Str_C'Access;
但编译器无法在上面提到的向量初始化中编译,并且说"前缀为" Access"属性必须是别名"
(之前我没有给char_array添加别名,因为char_array类型已经是别名的char数组。)
好的,让我们将别名关键字添加到char数组声明中:
Str_C : aliased Interfaces.C.Char_Array(1..23) := (others => Interfaces.C.nul);
不知道这里出了什么问题。任何帮助将不胜感激!
答案 0 :(得分:1)
我认为,这是关于左侧的明确子类型约束1..23
,Str_C
的类型char_array
上的子类型界限。 (私有)指针类型chars_ptr
是无约束的无约束对象,反映了C char*
(它不知道边界)。所以,声明这样的对象:
Str_C : aliased Interfaces.C.char_array := (1..23 => Interfaces.C.nul);
Ptr1 : Interfaces.
C.Strings.chars_ptr := Interfaces.C.Strings.To_Chars_Ptr(Str_C'access);
To_Chars_Ptr
执行必要的指针转换。声明实际上反映了编译器的诊断。
可能值得考虑To_Ada
,To_C
和Convention
标识符以及语言功能:Ada将数组作为C指针传递给C函数。这在LRM Annex B.3中有记录(请参阅实施建议)。因此,如果您愿意,可以在Ada端存储Ada字符串。
由于问题似乎也涉及指向对象的可访问性(例如,在子程序中声明的数组),这里有一些方法。有关详细信息,请参阅LRM 3.10.2。要问的重要问题是:"当指向它们的指针仍然可以传递时,对象是否存在?"例如,确保在子程序完成后存在对象可以通过在子程序中分配数组来实现,而不是将它们声明为堆栈上的变量。 (堆栈变量在调用后基本上会消失)。或者,如果您真的知道自己在做什么,则可以强制编译器忽略指针可能使用'Unchecked_Access
而不是'Access
比其对象更长。
Ptr2 : Interfaces.C.Strings.chars_ptr := -- DANGER AHEAD!
Interfaces.C.Strings.To_Chars_Ptr(Str_C'UNCHECKED_ACCESS);
Ptr3 : Interfaces.C.Strings.Chars_Ptr := Interfaces.C.Strings.To_Chars_Ptr
(new Interfaces.C.char_array'(1..23 => Interfaces.C.nul));
Ptr4 : Interfaces.C.Strings.Chars_Ptr :=
Interfaces.C.Strings.New_Char_Array((1..23 => Interfaces.C.nul));
答案 1 :(得分:0)
New-String函数是您想要做的完美工具:
with Interfaces.C.Strings; use Interfaces.C.Strings;
procedure Main_Ada is
Nom : constant chars_Ptr := New_string("Charles Dupont");
...