/ / स्विफ्ट रीडिंग चार (सी नहीं *) सी स्ट्रिंग पॉइंटर के रूप में - स्विफ्ट, ऑक्स

सी स्ट्रिंग पॉइंटर के रूप में स्विफ्ट रीडिंग (चार * नहीं) - स्विफ्ट, ओएससी

मैंने इस सप्ताह स्विफ्ट के साथ शुरुआत की, विशेष रूप से स्विफ्ट 4 के साथ, और मैं एक ब्रिजिंग हेडर के माध्यम से सी लाइब्रेरी का उपयोग कर रहा हूं, liblo, जो ओएससी (ओपन साउंड कंट्रोल) भेजने / प्राप्त करने के लिए एक नेटवर्क सॉकेट पर संदेश स्वरूपित करता है।

मैं एक सर्वर थ्रेड शुरू करने में सक्षम हूं, ओएससी प्राप्त करता हूंC कॉलबैक के माध्यम से संदेश-> स्विफ्ट को बंद करें, और स्विफ्ट के साथ संख्यात्मक तर्क मूल्यों को ठीक से पढ़ें। मैं स्ट्रिंग मान पढ़ने के साथ, हालांकि, मुसीबत में चल रहा हूं।

लिबेलो मेसेज तर्क प्रकार lo_arg एक संघ के लिए एक C टाइपडिफ है और स्ट्रिंग तर्क प्रकारों को सरल वर्णों के रूप में घोषित किया जाता है, जिन्हें Int8 के रूप में स्विफ्ट में मैप किया जाता है।

C में, आप स्ट्रिंग को पकड़ सकते हैं &argv[i]->s आपके कॉलबैक से lo_arg **argv सरणी। परिवाद के साथ एक ओब्ज-सी परियोजना में, मैं उपयोग करता हूं:

// get string value of first argument
lo_arg arg = argv[0];
NSString *s = [NSString stringWithUTF8String:&arg->s];
// do something with s

स्विफ्ट में, मैंने "Int8 का पता प्राप्त करने की कोशिश की और इसे स्ट्रिंग को खिलाया जो काम करता है, लेकिन केवल पहले अक्षर को पकड़ लेता है:

// get string value of first argument
if var arg : lo_arg = argv?.pointee![0] {
withUnsafePointer(to: &arg.s) {
let s = String(cString: $0)
// so something with s
}
}

क्या मुझसे कुछ ग़लत हो रहा है? मुझे लगता है कि ये समतुल्य होंगे लेकिन गुजर रहे होंगे $0 सेवा मेरे strlen() आला print("strlen: (strlen($0)") केवल "1" की लंबाई प्रिंट करता है। मैं सत्यापित करता हूं कि एक मल्टी-कैरेक्टर स्ट्रिंग वास्तव में एक गैर-स्विफ्ट परीक्षण कार्यक्रम के साथ भेजा जा रहा है। मैं सोच रहा हूं कि अगर स्विफ्ट किसी तरह स्ट्रिंग के सी एड्रेस पते के बजाय एक एकल वर्ण मान रहा है और / या मुझे कुछ और चाहिए सूचक रूपांतरण।

उत्तर:

जवाब के लिए 0 № 1

कुछ खुदाई के बाद, मैं स्विफ्ट ट्रंकट्स की पुष्टि कर सकता हूं lo_arg->s और lo_arg->S मेरे 64 बिट सिस्टम उर्फ ​​पर 8 बाइट्स के लिए स्ट्रिंग मान sizeof(char)। यह तब होता है जब स्ट्रिंग को lo_arg से पढ़ने की कोशिश की जाती है स्विफ्ट से। उसी मूल्य को पढ़ना सी में ठीक काम करता है, इसलिए स्विफ्ट एक ही चार के लिए केवल स्थान से पढ़ने / आरक्षित करने की अनुमति देता है। स्विफ्ट से C तक lo_arg को फॉरवर्ड करना और स्ट्रिंग को प्रिंट करना printf() यह भी 8 वर्णों तक काटे गए तारों को दिखाता है।

तार को पढ़ने से बचने के लिए त्वरित फिक्स हैस्विफ्ट द्वारा उत्पन्न lo_arg से, C में कच्चे lo_message से lo_arg को पकड़ो, और char "पॉइंटर" को एक कॉस्ट चार पर ले जाएं * Swift एक वेरिएबल लेंथ स्ट्रिंग के रूप में समझेगा। यहाँ कुछ कार्य उपयोगिता कार्य हैं जो मैंने अपने ब्रिजिंग हेडर में जोड़े हैं:

/// return an lo_message argv[i]->s in a format Swift can understand as a String
const char* lo_message_get_string(lo_message message, int at) {
return (const char *)&lo_message_get_argv(message)[at]->s;
}

/// return an lo_message argv[i]->S in a format Swift can understand as a String
const char* lo_message_get_symbol(lo_message message, int at) {
return (const char *)&lo_message_get_argv(message)[at]->S;
}

स्विफ्ट में, मैं फिर एक स्ट्रिंग में परिवर्तित कर सकता हूं:

let s = String(cString: lo_message_get_string(msg, 0))
// do something with s