2012-02-13 52 views
6

什麼是這將等同於C.轉換阿達字符串到C無效*

鑄造 char*void*

我該接口的C庫的好辦法「中投」的阿達StringSystem.Adress。 C類型具有類型爲void*的屬性,並且庫的用戶通常將由C字符串指向的地址指定爲該值。例如:

struct my_type { 
    void* value; 
}; 

int main() { 
    my_type t; 
    t.value = "banana"; 
} 

如何在Ada中實現等同於Ada字符串?

我現在使用這種技術,但它似乎對我來說很腥。

declare 
    str : constant String := "banana"; 
    data : constant char_array := To_C(str); 
    mine : my_type; 
begin 
    mine.value := data(data'First)'Address; 
end; 

我行有任何解決方案,甚至阿達2012

+2

你應該看看'Interfaces.C.Strings'包,其中包含'chars_ptr'類型。您導入的C函數應該使用chars_ptr類型而不是void *。 – oenone 2012-02-13 09:55:16

+2

另外,請看這裏的建議解決方案:http://en.wikibooks.org/wiki/Ada_Programming/Types/access#Where_is_void.2A.3F – oenone 2012-02-13 10:10:41

+0

該類型的void *成員是void *,因爲它應該能夠把任何東西的地址;不只是一個字符串。這就是爲什麼'g ++'爲它生成Ada規範並使用'System.Address'。目前我發現這項技術目前正在發揮作用。也許這是健全的? – Anthony 2012-02-13 23:22:38

回答

2

你提到在您使用void*「,因爲它應該能夠採取的任何地址的評論;不只是一個字符串「。

那麼,人們不得不問一下,通用指針如何轉換成Ada,特別是如何利用打字和子打字功能。我認爲在這種情況下,「任何事物」都不能一般地解決;也就是說,如果你想保持構件的'靈活性',你必須犧牲Ada提供的類型系統的優勢。此外,我提交的是按原樣提交的,通常不可靠地用於「任何事情」。我說這是因爲沒有確定包含「任何東西」的長度的方法。如果它是一個字符串,那麼長度是從指向地址開始連續計數,直到第一個NUL字符(ASCII 0) 。然而,如果它不是一個字符串,那麼沒有確定長度的方法(我們如何知道數組[1,2,3]或OBJECT的長度/大小)......所以我們沒有方法來確定甚至是「任何東西」的長度。

確定長度是編寫穩定/安全代碼的一個重要因素,因爲如果你不邀請緩衝區溢出。


但是,留下了,如果你能提供對數據的一些信息,無論是通過參數或改變my_struct,那麼我們就可以使用這些信息來建立一個更好的類型轉換。 (一般來說,關於類型的信息越多越好,因爲您可以用以前不能使用的方式檢查數據的有效性;或者更好的是讓編譯器爲您檢查。)

Type Data_Type is Array(Positive Range <>) of Interfaces.Unsigned_8; 
    For Data_Type'Component_Size Use 8; 


Function Some_Data(Stream : not null access Ada.Streams.Root_Stream_Type'Class; 
        Length : In Positive) Return Data_Type is 
    begin 
    Return Result : Data_Type(1..Length) do 
     For Index in Result'Range loop 
      Interfaces.Unsigned_8'Read(Stream, Result(Index)); 
     end Loop; 
    End Return; 
    end Some_Data; 

您可以使用上述命令生成一個8位無符號整數數組,其中包含來自數據流的數據。它概述了在一般情況下你需要做什麼,但是因爲你正在使用C-imports,所以你可以做的是修改一下,這樣a)有一個Temp變量,它是一個像Result這樣的數組,但是使用For Temp'Address Use [...]將其覆蓋在my_type.value上,然後使用for-loop將其複製出來。

相關問題