在尝试将ADA绑定到第三方C / C ++库(SAPNWRFCSDK)时,我遇到了数组类型的类型推断问题:
第一个问题:
gcc(gcc -fdump-ada-spec)的Gnat-Binding-Generator为不同的索引范围生成了许多中间命名数组类型:
type anon3115_anon3128_array is array (0 .. 8) of aliased SAP_UC;
type anon3115_anon3131_array is array (0 .. 3) of aliased SAP_UC;
type anon3115_anon3134_array is array (0 .. 12) of aliased SAP_UC;
这些类型用于记录中。如果我想将这些字段传递给过程或函数,我希望有一个无界的类型签名,例如以下类型:
type SAP_UC_Array is array (Int range <>) of aliased SAP_UC;
但是生成的类型没有这个不能传递的子类型。 一种解决方案是将记录中的字段声明更改为:
field : SAP_UC_Array(0 .. 8);
但这意味着“处理”生成的绑定文件并更改所有定义。 是否可以创建具有指定索引范围的命名数组子类型或解决方案?
第二个问题:
某些数组类型定义具有等效的组件类型。
subtype RFC_CHAR is SAP_UC;
type RFC_DATE is array (0 .. 7) of aliased RFC_CHAR;
此数组定义不被视为与组件类型SAP_UC的数组等效。 有可能告诉Ada这些类型是等价的吗?
答案 0 :(得分:1)
你可以在Ada中这样说:
type SAP_UC_Array is array (Int range <>) of aliased SAP_UC;
subtype anon3115_anon3128_array is SAP_UC_Array (0 .. 8);
subtype anon3115_anon3131_array is SAP_UC_Array (0 .. 3);
subtype anon3115_anon3134_array is SAP_UC_Array (0 .. 12);
如果您已经知道这一点,我道歉,但我无法判断问题是否只是让Gnat-Binding-Generator生成subtype
声明。我无法帮助你解决GNAT问题。
关于第二个问题:每个type
声明都会创建一个新的,不同的类型;没有办法将两种不同的类型视为等价。 (在某些情况下,该语言会自动转换类型,但我认为仅在涉及匿名类型或某些特定类型的情况下,例如&#34;通用整数&#34;。)在这种情况下,但是,没有特别的理由声明像RFC_DATE
这样的数组类型。如果您的类型已经是SAP_UC
的数组,例如SAP_UC_Array
,那么您也可以说
subtype RFC_DATE is SAP_UC_Array (0 .. 7);
因为元素类型RFC_CHAR基本上只是一个&#34;重命名&#34; SAP_UC。 (当然,如果工具生成类型声明,这将无法帮助您。)
答案 1 :(得分:0)
现在我遇到了将Ada-String转换为SAP_UC_Array的挑战。实际上是一个功能
function toUnicode( adaString : String) return SAP_UC_Array;
是必需的。为此,我想使用C函数:
SAP_UC const * toUnicode( char const * s)
{
UConverter * converter;
UErrorCode err = U_ZERO_ERROR;
SAP_UC * target;
target = (SAP_UC *) calloc( strlen(s)+1, sizeof(SAP_UC) ); // Creating wonderfull Memory Leaks
converter = ucnv_open( "8859-1", &err );
int len = ucnv_toUChars(converter, target, strlen(s)+1, s, strlen(s), &err);
ucnv_close( converter );
return target;
}
可以映射此函数以产生access SAP_UC
- 与C-Pointer SAP_UC const *
的对应关系:
function toUnicode (arg1 : Interfaces.C.Strings.chars_ptr) return access SAP_UC;
pragma Import (C, toUnicode, "toUnicode");
我用toUnicode(New_String(adaString))
调用它并获取对第一个SAP_UC字符的引用。但我宁愿回到不受限制的SAP_UC_Array
。这可能吗?
嗯,我找到了一个解决方案 - 当然不优雅 - 但它确实有效。 一个C函数,允许以字符方式读出数组:
SAP_UC getChar(SAP_UC * u, int i)
{
return u[i];
}
带有相应的Ada-Signature:
function getChar(a : access SAP_UC; i: Int) return sapucx_h.SAP_UC;
pragma Import (C, getChar, "getChar");
在Ada我有一个函数,它按元素填充给定的SAP_UC_Array:
function sU( s : String; b : out SAP_UC_Array ) return SAP_UC_Array is
a : access SAP_UC;
begin
a := toUnicode( New_String(s));
for i in 0 .. Int'Val(s'length) loop
b(i) := getChar(a,i);
end loop;
return b;
end;
我正在使用“动态”内存分配:
function cU( s : String ) return SAP_UC_Array
is
begin
declare
tmp : SAP_UC_Array(0 .. s'length);
begin
return sU(s,tmp);
end;
end;
我确信有更好的解决方案。