【发布时间】:2020-02-22 20:49:33
【问题描述】:
我正在尝试使用与它所来自的 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语言中函数的原型:
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 位整数)数组。这让我非常恼火。这是适当的绑定:
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");
如您所见,绑定将 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?谢谢!
【问题讨论】:
标签: c pass-by-reference ada memory-address ffi