मैं एक बाइट सरणी + लंबाई से सी पास करने की कोशिश कर रहा हूं और चूंकि स्विफ्ट मौजूदा डेटा संरचना का उपयोग बाइट सरणी को इसमें निर्मित लंबाई के साथ स्टोर करने के लिए कर रहा है, मैं जानना चाहता हूं कि एक प्रतिकृति के साथ सी को पूरा करने के लिए एक तेज डेटा संरचना कैसे पास करें सी . में डेटा संरचना

एक परिणाम यह है कि मैं सी से तेजी से डेटा संरचना कैसे वापस कर सकता हूं?

मैंने सी हेडर फ़ाइल में संबंधित डेटा संरचना बनाने का प्रयास किया है:

typedef struct {
    const char *data;
    unsigned int count;
} CData;

अपने स्विफ्ट कोड में मैंने बाइट सामग्री को स्विफ्ट डेटा स्ट्रक्चर से सीडीटा स्ट्रक्चर में मार्शल करने की कोशिश की:

let swiftString = "Swift String"
let testString: [CChar]? = swiftString.cString(using: .utf8)
var data = Data()
data.append(contentsOf: Array(swiftString.utf8))

var cData = UnsafeMutablePointer<CData>.allocate(capacity: 1)
defer {
    cData.deallocate()
}
cData.pointee.count = UInt32(data.count)
cData.pointee.data = UnsafePointer(UnsafeMutablePointer<Int8>.allocate(capacity: data.count))
defer {
    cData.pointee.data.deallocate()
}
data.copyBytes(to: cData.pointee.data, count: data.count) // Cannot convert value of type 'UnsafePointer<Int8>?' to expected argument type 'UnsafeMutablePointer<UInt8>'

}

हालांकि, मुझे त्रुटि मिलती है 'UnsafePointer' प्रकार के मान को परिवर्तित नहीं कर सकता? जब मैं डेटा से सीडीटा में बाइट सामग्री की प्रतिलिपि बनाने का प्रयास करता हूं तो अपेक्षित तर्क प्रकार 'असुरक्षित म्यूटेबल पॉइंटर'

0
user962460 14 अप्रैल 2020, 17:00

1 उत्तर

सबसे बढ़िया उत्तर

सी साइड पर UInt8 के बराबर अहस्ताक्षरित चार होगा। इसलिए आपकी सी संरचना इस तरह दिखेगी:

typedef struct {
    const unsigned char *data;
    unsigned int count;
} CData;

फिर अपने प्रश्न में दिखाए गए रूपांतरण को थोड़ा समायोजित करें:

...
let bytes = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count)
cData.pointee.data = UnsafePointer(bytes)
defer {
    cData.pointee.data.deallocate()
}
data.copyBytes(to: bytes, count: data.count)

अंत में इसका परीक्षण करने के लिए, कोई निम्नलिखित को सी-साइड पर परिभाषित कर सकता है:

void transfer_data(CData *data) {
    printf("length: %d\n", data->count);
    for(int i = 0; i < data->count; i++) {
        printf("%c(0x%x) ", data->data[i], data->data[i]);
    }
    printf("\n");
}

आप इसे स्विफ्ट से सी-डाइलिब के अंदर इस तरह कह सकते हैं:

typealias transferDataFunc = @convention(c) (UnsafeMutablePointer<CData>) -> Void

...
let transfer_data_sym = dlsym(handle, "transfer_data")
let transferData = unsafeBitCast(transfer_data_sym, to: transferDataFunc.self)
transferData(cData)

यह डीबग कंसोल पर निम्न आउटपुट करेगा:

length: 12
S(0x53) w(0x77) i(0x69) f(0x66) t(0x74)  (0x20) S(0x53) t(0x74) r(0x72) i(0x69) n(0x6e) g(0x67) 
1
Stephan Schlecht 14 अप्रैल 2020, 15:11