我有Ada.Strings.Unbounded.Unbounded_String
,我想传递给C函数,该函数在Ada中使用char *
(Interfaces.C.chars_ptr
。
我当前的实现涉及将无界字符串复制到固定字符串,然后将固定字符串复制到chars_ptr
。
F_String : String := To_String (UB_String);
C_String : chars_ptr := New_String (F_String);
请注意,这会复制两次,最后我只会调用
Imported_Function (C_String);
Free (C_String);
弃用F_String
。
我是否可以使用最少的复制实现所需的行为(将Unbounded String中保存的字符串传递给导入的C函数)?理想情况下,将UB_String
的内部缓冲区直接传递给函数会很酷,但这可能不是可移植的。我是否至少可以在不需要中间固定字符串的情况下实现相同的行为?
我看到GNAT有内部包Ada.Strings.Unbounded.Aux
,它允许您访问Unbounded String的内部缓冲区,但这不可移植,并且可能在GNAT版本之间中断。
答案 0 :(得分:1)
ada中的字符串操作是一种痛苦,除了首先避免使用无界字符串(可能只在记录中需要字符串字段时才使用它们),你可以做的事情并不多。
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Interfaces.C; use Interfaces.C;
...
procedure Imported_Function(Item : in access Interfaces.C.Char);
pragma Import(C, Imported_Function, "...");
Item : aliased Interfaces.C.Char_Array := To_C(To_String(UB_String)); -- no need to free
begin
Imported_Function(Item(Item'first)'access);
...
答案 1 :(得分:1)
简短且令人失望的答案是:不是以便携方式。
但是你有一些选择:
广告。 1:
好像你已经找到了如何挂钩GNAT Ada.Strings.Unbounded包。
广告。 2:
考虑如何“无限制”你的字符串类型真的必须。你知道长度上几乎是一定的上限吗?在最糟糕的情况下,为每个字符串分配两倍的VM页面是不合理的吗?如果没有分配足够的内存,什么是可接受的操作?失败?分配更多和复制?创建链接列表然后必须为“导出”目的制作副本?在Ada中创建自定义类型并不是那么困难,所以请考虑一下,如果您有一些特殊要求(就像在这种情况下听起来那样)。