1

我有一个Ada.Strings.Unbounded.Unbounded_String,我想将它传递给一个 C 函数,该函数需要一个char *(Interfaces.C.chars_ptr在 Ada 中)。

我当前的实现涉及将无界字符串复制到固定字符串,然后将固定字符串复制到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

我可以使用最少的复制来实现所需的行为(将无界字符串中保存的字符串传递给导入的 C 函数)吗?理想情况下,将内部缓冲区 UB_String直接传递给函数会很酷,但这可能不是可移植的。我至少可以在不需要中间固定字符串的情况下实现相同的行为吗?

我看到 GNAT 有一个内部包Ada.Strings.Unbounded.Aux,它允许您访问无界字符串的内部缓冲区,但这不是可移植的,并且可能会在 GNAT 版本之间中断。

4

2 回答 2

1

简短而令人失望的答案是:不是以便携的方式。

但是您有一些可用的选项:

  1. 放弃可移植性并挂钩到编译器随附的特定版本标准库的内部。
  2. 编写您自己的字符串类型,这符合您的要求。
  3. 接受额外的副本,直到您发现它对您的应用程序有问题。

广告。1:

您似乎已经了解了如何挂钩 GNAT Ada.Strings.Unbounded 包。

广告。2:

考虑一下您的字符串类型实际上必须是多么“无界”。你知道长度的一个几乎确定的上限吗?在最坏的已知情况下,为每个字符串分配两倍于实际需要的 VM 页面是否不合理?如果您没有分配足够的内存,什么是可接受的操作?失败?分配更多并复制?创建一个链接列表,然后必须为“导出”目的制作一个副本?在 Ada 中创建自定义类型并不是那么困难,因此请考虑一下,如果您有一些特殊要求(就像在这种情况下听起来那样)。

于 2013-10-03T07:11:47.093 回答
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);
  ... 
于 2013-10-01T11:18:17.127 回答