我正在寻找将字符串传递给C函数的不同方法。这是一个关于4种不同方式的示例,代码经过测试并且有效。
with Interfaces.C; use Interfaces.C;
with Interfaces.C.Strings; use Interfaces.C.Strings;
with System; use System;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Real_Time; use Ada.Real_Time;
procedure Main is
procedure Strcpy (Target : out String; Source : in String) with Import, Convention => C, External_Name => "strcpy";
procedure Strcpy (Target : Address; Source : Address) with Import, Convention => C, External_Name => "strcpy";
procedure Strcpy (Target : out char_array; Source : in char_array) with Import, Convention => C, External_Name => "strcpy";
procedure Strcpy (Target : chars_ptr; Source : chars_ptr) with Import, Convention => C, External_Name => "strcpy";
Source : String := "Duration: " & Character (nul);
Target_String : String (Source'Range) := (others => ' ');
Target_String_Address : String (Source'Range) := (others => ' ');
Target_char_array : char_array (size_t (Source'First) .. size_t (Source'Last)) := (others => ' ');
Target_chars_ptr : chars_ptr := New_Char_Array (Target_char_array);
T : Time;
D : Time_Span;
N : constant := 100000000;
begin
T := Clock;
for I in 1..N loop
Strcpy (Target_String, Source);
end loop;
D := Clock - T;
Put_Line (Target_String & To_Duration(D)'Img);
T := Clock;
for I in 1..N loop
Strcpy (Target_String_Address'Address, Source'Address);
end loop;
D := Clock - T;
Put_Line (Target_String_Address & To_Duration(D)'Img);
T := Clock;
for I in 1..N loop
Strcpy (Target_char_array, To_C (Source));
end loop;
D := Clock - T;
Put_Line (To_Ada (Target_char_array) & To_Duration(D)'Img);
T := Clock;
for I in 1..N loop
Strcpy (Target_chars_ptr, New_String (Source));
end loop;
D := Clock - T;
Put_Line (Value (Target_chars_ptr) & To_Duration(D)'Img);
end;
测量
╔════════════╦════════════╦═════════════╗
║ Type ║ Conversion ║ Duration[s] ║
╠════════════╬════════════╬═════════════╣
║ String ║ ║ 0.564774366 ║
║ Address ║ ║ 0.535110315 ║
║ char_array ║ To_C ║ 2.938592901 ║
║ chars_ptr ║ New_String ║ 6.790939748 ║
╚════════════╩════════════╩═════════════╝
考虑到良好的表现,我应该使用哪种方法?
传递String'Address将获得最佳性能,但我应该这样做吗?
任何Strcpy程序都有任何缺点吗?
任何Strcpy程序都有什么好处吗?
答案 0 :(得分:3)
我不打算为你衡量表现。我希望你能够自己做到这一点。
您无法保证Standard.String
个对象可以以始终有效的方式传递给任何C函数,因为Ada编译器不需要期望{{{{{{ 1}}别名。如果您确保Standard.String
等同于Interfaces.C.char
,那么类型为Standard.Character
的对象已打包,并且类型为Standard.String
的对象为空终止,那么我预计它可以在大多数情况下使用。
包装和等效是您必须通过实验检查作为自动构建和测试程序的一部分。
您可以使用Standard.String
的子类型以及导入的C函数的形式参数的动态谓词来强制执行空终止:
Standard.String
如果你假设遵循LRM中的B.3(70)(技术上它只是实现建议,但我认为这是一个安全的假设),那么你可以直接在界面中使用with Ada.Characters.Latin_1;
package Strings_For_C is
NUL : constant Character := Ada.Characters.Latin_1.NUL;
subtype C_String is Standard.String
with Dynamic_Predicate => C_String'Length >= 1 and then
C_String (C_String'Last) = NUL;
end Strings_For_C;
导入的C程序代替C_String
参数:
char*