Как передать CFData в C char **? - PullRequest
0 голосов
/ 24 августа 2018

Из C мне нужно вызвать некоторый код Swift, который принимает входной байтовый массив и создает выходной байтовый массив.

Это в заголовке моста:

typedef void (*SwiftFunc)(const uint8_t* input, int inputLen, uint8_t** output, int* outputLen);

extern "C" void CFunc(SwiftFunc swiftFunc);

Вот реализация C CFunc:

void CFunc(SwiftFunc swiftFunc) {
    char* input = "Hello world";
    int inputLen = strlen(input);
    char* output = NULL;
    int outputLen = 0;
    swiftFunc(input, inputLen, &output, &outputLen);
    // do something with the output here
}

А вот и код Swift:

func swiftFunc(
    input: Optional<UnsafePointer<UInt8>>, 
    inputLen: Int32,
    output:Optional<UnsafeMutablePointer<
             Optional<UnsafeMutablePointer<UInt8>>>>, 
    outputLen:Optional<UnsafeMutablePointer<Int32>>) -> Void {

        let cfInput = CFDataCreate(kCFAllocatorDefault, input, CFIndex(inputLen))
        let cfOutput = ... generate the output ...

        How to pass the output buffer back to C?
}

Как передать выходной буфер из Swift в C? Учитывая, что задействован двойной указатель.

Кроме того, подпись функции Swift кажется очень многословной, это ожидается? Я попытался использовать суффиксы ? вместо Optional<>, но компилятору это не понравилось.

1 Ответ

0 голосов
/ 24 августа 2018

Все, что вам нужно сделать, это установить свойство pointee для UnsafeMutablePointer<UnsafeMutablePointer<UInt8>> в экземпляр UnsafeMutablePointer<UInt8>. При вашем текущем подходе функция Swift обязана выделять память, связанную с выходным буфером.

Вызов UnsafeMutablePointer<UInt8>.allocate(MemoryLayout<UInt8>.stride * outputLength) примерно эквивалентен вызову malloc и необходим в этом случае использования. После создания буфера с правильным распределением памяти, инициализируйте его значения с cfOutput. Например, если cfOutput имеет тип [UInt8], вы можете сделать следующее:

for i in 0..<cfOutput.count {
    buf[i] = cfOutput[i]
}

После инициализации значений в выходном буфере просто установите output?.pointee на UnsafeMutablePointer<UInt8>, который вы только что присвоили и инициализировали.

Ниже приведен пример того, как вы можете передать выходной буфер обратно в C.

func swiftFunc(input: UnsafePointer<UInt8>!,
               inputLen: Int32,
               output: UnsafePointer<UnsafePointer<UInt8>>?,
               outputLen: UnsafePointer<UInt8>?) {
    let cfInput = CFDataCreate(kCFAllocatorDefault, input, CFIndex(inputLen))
    let cfOutput = // Generate your output.

    let bufLen = // Determine output buffer length.
    let buf = UnsafeMutablePointer<UInt8>.allocate(MemoryLayout<UInt8>.stride * bufLen)

    // Initialize 'buf' with 'cfOutput' somehow.

    output?.pointee = buf
    outputLen?.pointee = Int32(bufLen)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...