使用Interfaces.C.Strings.Char_Array_Access

时间:2016-03-21 10:20:47

标签: arrays char ada

我正在开发一个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);

但它仍然失败,矢量线上的错误如下: enter image description here

并在char数组声明行上发出警告: enter image description here

不知道这里出了什么问题。任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:1)

我认为,这是关于左侧的明确子类型约束1..23Str_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_AdaTo_CConvention标识符以及语言功能: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");
...