- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
将结构/记录数组从 Ada 传递到 C 例程是一回事。在这种情况下,内存管理是在 Ada 中完成的。但是在与第三方库接口(interface)时,经常会出现内存管理在 C 部分完成的问题。
例如:对于 C 结构:
typedef struct _MYREC
{
int n;
char *str;
} MYREC;
以下 C 例程分配内存并返回指向具有 n 个元素的 MYREC 数组的指针:
MYREC * allocMyrec(int n);
问题是返回的指针不包含 Ada 中内存安全计算所需的大小信息。
在 Ada 中,我想为 (MYREC *)
指针使用相应的数组定义:
type MYREC_Array is array (Int range <>) of aliased MYREC;
pragma Convention (C, MYREC_Array);
相应的(大小感知)Ada-Function allocMyrec
会是什么样子或者什么是正确的策略?
顺便说一句对于一个元素,可以将 C 指针映射到 access MYREC
。这就是 Gnat-Binding 生成器所做的。但这没有帮助。
高度赞赏提示。
最佳答案
我终于使用 Interface.C.Pointers
包让它工作了,这很容易,这是代码:
with Interfaces.C, Interfaces.C.Pointers ;
use Interfaces.C ;
with Ada.Text_IO ; -- To Check
procedure MYRECTest is
package IIO is new Ada.Text_IO.Integer_IO (Int) ;
type PChar is access all Char ;
type MYREC is record
N : Int ;
Str : PChar ;
end record ;
pragma Convention(C, MYREC);
DefaultMyrec : MYREC := (0, null) ;
type MYREC_Array is array (Int range <>) of aliased MYREC ;
pragma Convention(C, MYREC_Array); -- Not sure if useful...
-- Here is the trick
package PMYREC is new Interfaces.C.Pointers (Int, MYREC, MYREC_Array, DefaultMyrec) ;
function AllocMyrec (N : in Int) return PMYREC.Pointer ;
pragma Import (C, AllocMyrec, "allocMyrec");
P : PMYREC.Pointer := AllocMyrec(5) ;
StartP : PMYREC.Pointer := P ; -- Initial pointer
A : MYREC_Array(0..4) := PMYREC.Value(P, 5) ; -- Here is a copy
begin
for I in A'Range loop
-- Real access:
IIO.Put(P.all.N) ;
P.all.N := P.all.N + 3 ; -- Here you're really accessing the allocated memory, not just a copy
PMYREC.Increment(P) ;
-- 'Fake' access:
IIO.Put(A(I).N) ;
A(I).N := A(I).N + 3 ; -- Here you're accessing a copy, so the modification is not made on the allocated memory
end loop ;
Ada.Text_IO.New_Line ;
end MYRECTest ;
我测试了上面的代码,将 C 函数中所有 _MYREC
元素的 n
属性设置为 42 + i
并将其打印在Ada body,它起作用了(我得到了 42、43、44、45、46)。 C 函数看起来像(用于测试):
typedef struct _MYREC {
int n ;
char *str ;
} MYREC ;
MYREC * allocMyrec (int n) {
MYREC *res = malloc(n * sizeof(MYREC)) ;
int i ;
for (i = 0 ; i < n ; i++) {
res[i].n = 42 + i;
}
return res ;
}
DefaultMyrec
变量无用,但对于包创建是必需的。我假设您总是使用带有 length
参数的 Value
函数来检索值。
关于包裹的更多信息:http://www.adaic.org/resources/add_content/standards/05rm/html/RM-B-3-2.html
编辑:原始代码正在复制 P
指向的内存,因此如果您更新数组 A
中的任何内容,它会赢' 改变分配的内存。事实上,您应该直接使用指针 P,如编辑后的代码所示。
编辑: 我为 MYREC
的 str
属性使用了一个“愚蠢的”access all Char
但你如有必要,可以(并且应该)使用 Interfaces.C.Pointers
中几乎相同的内容。我对其进行了测试,但不想将其放入答案中,因为它没有添加任何内容。
关于c - 将从 C 例程分配的数组传递给 Ada,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23364380/
我最近购买了《C 编程语言》并尝试了 Ex 1-8这是代码 #include #include #include /* * */ int main() { int nl,nt,nb;
早上好!我有一个变量“var”,可能为 0。我检查该变量是否为空,如果不是,我将该变量保存在 php session 中,然后调用另一个页面。在这个新页面中,我检查我创建的 session 是否为空,
我正在努力完成 Learn Python the Hard Way ex.25,但我无法理解某些事情。这是脚本: def break_words(stuff): """this functio
我是一名优秀的程序员,十分优秀!