gpt4 book ai didi

c - 我如何在 Ada 中处理一个 int** ?

转载 作者:太空宇宙 更新时间:2023-11-04 01:16:09 28 4
gpt4 key购买 nike

我正在尝试使用预制绑定(bind)到它来自的 C 库来调用 SDL_LoadWAV。 SDL_LoadWAV 只是 SDL_LoadWAV_RW 的包装器:

function SDL_LoadWAV
(file : C.char_array;
spec : access SDL_AudioSpec;
audio_buf : System.Address;
audio_len : access Uint32) return access SDL_AudioSpec
is
begin
return SDL_LoadWAV_RW
(SDL_RWFromFile (file, C.To_C ("rb")),
1,
spec,
audio_buf,
audio_len);
end SDL_LoadWAV;

这是 C 函数的原型(prototype):

SDL_AudioSpec* SDL_LoadWAV_RW(SDL_RWops*     src,
int freesrc,
SDL_AudioSpec* spec,
Uint8** audio_buf,
Uint32* audio_len)

(See here for more information)

现在如您所见,它以 Uint8** 的形式通过引用传递 Uint8(无符号 8 位整数)数组。这让我很苦恼。这是适当的绑定(bind):

function SDL_LoadWAV_RW
(src : access SDL_RWops;
freesrc : C.int;
spec : access SDL_AudioSpec;
audio_buf : System.Address;
audio_len : access Uint32) return access SDL_AudioSpec;
pragma Import (C, SDL_LoadWAV_RW, "SDL_LoadWAV_RW");

如您所见,绑定(bind)将 Uint8** 映射到 System.Address。我已经尝试了一些技巧来将数据获取到我想要的位置,但似乎没有任何效果。现在,我的代码如下所示(其中包含一些自定义类型和异常):

type Music is new Resource with
record
--Id : Integer; (Inherited from Resource)
--Filename : Unbounded_String; (Inherited from Resource)
--Archive_Name : Unbounded_String; (Inherited from Resource)
--Zzl_Size : Integer; (Inherited from Resource)
Audio : access SDL_AudioSpec_Access;
Length : aliased Uint32;
Buffer : System.Address;
Position : Integer := 1;
end record;

overriding procedure Load(Mus : in out Music) is
Double_Pointer : System.Address;
begin
Log("Loading music " & To_Ada(Get_Audio_Filepath(Mus)));
Audio_Load_Lock.Seize;
if null = SDL_LoadWAV(Get_Audio_Filepath(Mus), Mus.Audio.all, Double_Pointer, Mus.Length'access) then
raise Audio_Load_Failed with To_String(Mus.Filename) & "&Stack=" & Get_Call_Stack;
end if;
Log("Music length =" & Integer'Image(Integer(Mus.Length)));
declare
type Sample_Array is array(1..Mus.Length) of Uint8;
Single_Pointer : System.Address;
for Single_Pointer'address use Double_Pointer;
pragma Import(Ada, Single_Pointer);
Source : Sample_Array;
for Source'address use Single_Pointer;
pragma Import(Ada, Source);
Dest : Sample_Array;
for Dest'address use Mus.Buffer;
pragma Import(Ada, Dest);
begin
Dest := Source;
end;
Audio_Load_Lock.Release;
end Load;

但是,就像我尝试过的或多或少的其他所有事情一样,我在执行 Load 函数时收到 PROGRAM_ERROR/EXCEPTION_ACCESS_VIOLATION。

谁能知道我需要如何处理这个 System.Address?谢谢!

最佳答案

definition of SDL_LoadWAV_RW

This function, if successfully called, returns a pointer to an SDL_AudioSpec structure filled with the audio data format of the wave source data. audio_buf is filled with a pointer to an allocated buffer containing the audio data, and audio_len is filled with the length of that audio buffer in bytes.

这意味着被调用函数分配所需的内存并填充它,然后返回指向分配的内存及其长度的指针。

所以提供给您的绑定(bind)不是很好的 Ada。

audio_buf 应该是字节数组的 out 参数,audio_lenout 参数 Uint32.

作为演示,使用这个 C:

#include <stdlib.h>
void get_data (char **buf, int *len)
{
*len = 10;
*buf = malloc(*len);
for (int j = 0; j < *len; j++) {
(*buf)[j] = j;
}
}

这个艾达

type Raw is array (Interfaces.Unsigned_32) of Interfaces.Unsigned_8
with Convention => C;

定义了一个数组类型(如果我们实际声明一个数组类型,它将占用 2^32-1 个字节!),而这个

type Raw_P is access all Raw
with Convention => C, Storage_Size => 0;

定义了一个指向这样一个数组的指针。将存储大小限制为 0 意味着我们不能说 new Raw_P

把这些放在一起,

with Ada.Text_IO; use Ada.Text_IO;
with Interfaces;
procedure Demo is
type Raw is array (Interfaces.Unsigned_32) of Interfaces.Unsigned_8
with Convention => C;

type Raw_P is access all Raw
with Convention => C, Storage_Size => 0;

procedure Get_Data (In_Buffer : out Raw_P;
Length : out Interfaces.Unsigned_32)
with
Import,
Convention => C,
External_Name => "get_data";

Allocated : Raw_P;
Length : Interfaces.Unsigned_32;

use type Interfaces.Unsigned_32;
begin
Get_Data (In_Buffer => Allocated,
Length => Length);
for J in 0 .. Length - 1 loop
Put (Allocated (J)'Image);
end loop;
New_Line;
end Demo;

给出一个程序,运行结果为

$ ./demo
0 1 2 3 4 5 6 7 8 9
$

----

认识到你可能陷入困境

audio_buf : System.Address;

你可以定义(或使用,如果已经定义的话)像我的RawRaw_P 和 say

procedure Get_Data (In_Buffer : System.Address;
Length : out Interfaces.Unsigned_32)
with
Import,
Convention => C,
External_Name => "get_data";

然后使用

Get_Data (In_Buffer => Allocated'Address,
Length => Length);

关于c - 我如何在 Ada 中处理一个 int** ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58576503/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com