![](/img/trans.png)
[英]How Do I Read “int (*functionFactory(int n))(int, int) { … }”?
[英]How do I handle an int** in Ada?
我正在嘗試使用與它來自的 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中的function的原型:
SDL_AudioSpec* SDL_LoadWAV_RW(SDL_RWops* src,
int freesrc,
SDL_AudioSpec* spec,
Uint8** audio_buf,
Uint32* audio_len)
現在您可以看到,它通過引用以 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。 我已經嘗試了一些技巧來獲取我想要的數據到 go,但似乎沒有任何效果。 現在,我的代碼看起來像這樣(它有一些自定義類型和異常):
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 function 時,我得到了 PROGRAM_ERROR/EXCEPTION_ACCESS_VIOLATION。
誰能弄清楚我需要如何處理這個 System.Address? 謝謝!
這個function如果調用成功,則返回一個指向SDL_AudioSpec結構的指針,該結構填充了波源數據的音頻數據格式。 audio_buf 填充了指向包含音頻數據的已分配緩沖區的指針,而 audio_len 填充了該音頻緩沖區的長度(以字節為單位)。
這意味着被調用的 function 分配所需的 memory 並填充它,然后返回指向分配的 memory 的指針及其長度。
所以你得到的綁定不是很好,艾達。
audio_buf
應該是字節數組的out
參數, Uint32
應該是audio_len
的out
參數。
作為演示,使用此 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;
你可以定義(或使用,如果已經定義)像我的Raw
, Raw_P
和說
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);
SDL_LoadWAV 將在您提供的位置寫入一個指針(指向由 SDL 分配的新緩沖區),即未初始化變量 Double_Pointer 的值,它是一個隨機地址 -> kaboom!
在調用 SDL_LoadWAV 之前,您需要具備以下條件:
Double_Pointer := SDL_Buffer'Address;
其中SDL_Buffer
以前是這樣定義的:
type Buffer_Access_Type is access all Buffer_Type;
SDL_Buffer: Buffer_Access_Type;
根據 API,您需要稍后使用SDL_FreeWAV
SDL_Buffer
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.