我開始學習 C 并想嘗試一些 Swift-C 互操作性。
我有一個小的 C 函式,它讀取我一個檔案并將一些有用的字母連接到一個 char* 變數中。經過一些測驗,我找不到將獲得的 char* 資料快速傳回的方法。我寫了一個小的虛擬代碼來說明我想要實作的目標。
var letters: [CChar] = []
functionWithArray(&letters)
print("Back in swift: \(letters)")
C函式是:
void functionWithArray(char* letters) {
int arrayLenght = 5;
int testLenght = 10; // Expand array to this value (testing)
int currentArrayPosition = 0; //Keep track of the assigned values
letters = malloc(sizeof(char)*arrayLenght);
while (currentArrayPosition < testLenght) {
if (currentArrayPosition == arrayLenght) {
arrayLenght ;
letters = realloc(letters, sizeof(char)*arrayLenght);
}
letters[currentArrayPosition] = *"A";
currentArrayPosition;
}
printf("End of C function: %s\n", letters);
}
我得到這個作為輸出:
C 函式結束:AAAAAAAAAA
迅速回傳:[]
程式以退出代碼結束:0
如您所見,在 C 函式內部,我得到了所需的結果,但很快我就找不到獲取修改后陣列的方法。我不直接使用該函式回傳字母,因為我需要從該函式回傳更多值。我是C新手,所以請善待。
uj5u.com熱心網友回復:
您的方法在這里有兩個主要問題——一個在 C 中,一個在 Swift 中:
在 C 中,函式引數是按值傳遞的,并且實際上是可變的區域變數。這意味著當
functionWithArray接收時char *letters,letters是一個區域變數,其中包含指向letters記憶體緩沖區的指標值。重要的是,這意味著這letters是可分配的,但不是您認為的那樣:letters = malloc(sizeof(char)*arrayLenght);通過 分配一個全新的緩沖區
malloc,并將新創建的指標值分配給您的區域letters變數。在賦值之前,letters是一個指向你從 Swift 獲得的緩沖區的指標;之后,到記憶體中不相關的緩沖區。這兩個緩沖區彼此完全無關,并且因為letters只是一個區域變數,所以這個賦值不會以任何方式在函式之外傳播。請注意,這只是 C 的一條規則:隨著您對 C 的了解更多,您可能會發現,為了將變數從函式內部分配到函式外部,您需要將變數包裝在另一層指標中并通過該指標寫入(例如,您需要接收
char **letters和分配*letters = malloc(...)以對傳入的變數產生任何影響——并且該變數不能直接傳入,而是需要傳入其地址)。但是,您通常不能利用這個事實,因為,
Array<T>an到 an的隱式轉換UnsafeMutablePointer<T>(例如,在 Swift 中的[CChar]→UnsafeMutablePointer<CChar>==char *在 C 中)不允許您將全新的緩沖區分配給陣列實體。您可以通過寫入指標值來寫入緩沖區的內容,但您不能分配新的記憶體塊并將陣列的內容重新分配給該新塊
相反,您需要:
functionWithArray從 C 回傳一個全新的陣列和長度 - 你提到這是不可能的,因為functionWithArray它需要回傳其他值,但理論上你也可以創建一個 Cstruct將所有回傳值包裝在一起并回傳一個那些而不是重寫
functionWithArray以接收一個陣列和一個長度,并預先在陣列中預留足夠的空間以適當地填充它:var letters: [CChar] = [] letters.reserveCapacity(/* however much you need */) functionWithArray(&letters, letters.capacity)在
functionWithArray中,不要重新分配字母,而是將其填入capacity給您的結果。當然,這只有在你提前知道 SwiftfunctionWithArray需要多少空間的情況下才有效,而你可能不會- 或者,您也可以通過預先分配一些空間
Array.init(unsafeUninitializedCapacity:initializingWith:)來組合這些操作,并且您可以傳遞給 C,如果需要,您可以在其中 分配記憶體并分配給緩沖區指標,然后寫出您有多少陣列元素分配和初始化。不過,這也需要容量,并且是一個更復雜的解決方案Arrayinout UnsafeMutableBufferPointer<CChar>inout Int
- 或者,您也可以通過預先分配一些空間
Of these two approaches, if functionWithArray really does need to dynamically reallocate memory and grow the buffer, then (1) is likely going to be easier.
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/450994.html
