如何将Float二维数组转为UnsafeMutablePointer<UnsafeMutablePointer<Float>>传递给OC++函数
UnsafeMutablePointer<UnsafeMutablePointer<Float>> for Objective-C++ Framework Calls Great question! Dealing with unsafe pointer conversions between Swift and Objective-C++ can feel tricky at first, but once you break down the type mapping, it’s pretty straightforward. Let’s walk through exactly what you need to do.
First, let’s clarify the type match:
The Objective-C++ function expects a float** (a pointer to an array of Float pointers), which Swift translates to UnsafeMutablePointer<UnsafeMutablePointer<Float>?>!. The ? just means individual pointers in the array can be nil (if your framework allows that), but if you’re passing a fully populated 2D array, you can safely work with non-nil pointers.
Scenario 1: Converting an Existing Swift [[Float]] Array
If you already have a Swift 2D Float array, you’ll need to manually copy its contents into memory the Objective-C++ function can safely access (since Swift’s array memory is managed and might be deallocated if the array goes out of scope). Here’s how:
// Your existing Swift 2D array let swift2DArray: [[Float]] = [ [0.5, 1.0, 1.5], [2.0, 2.5, 3.0] ] // Step 1: Create an array of mutable pointers, one for each subarray var pointerBuffer: [UnsafeMutablePointer<Float>?] = [] for subArray in swift2DArray { let elementCount = subArray.count // Allocate memory for the subarray let subPtr = UnsafeMutablePointer<Float>.allocate(capacity: elementCount) // Copy the Swift subarray's contents into the allocated memory subPtr.initialize(from: subArray, count: elementCount) pointerBuffer.append(subPtr) } // Step 2: Get a mutable pointer to the pointer array (this is your `args` parameter) let args = UnsafeMutablePointer<UnsafeMutablePointer<Float>?>(&pointerBuffer) // Now call your framework function yourFrameworkObject.applyFilters( input_image, input_params: input_params, output_image: output_image, output_params: output_params, filter_id: yourFilterID, args: args ) // Critical: Clean up the manually allocated memory to avoid leaks for (index, ptr) in pointerBuffer.enumerated() { guard let validPtr = ptr else { continue } // Deinitialize the memory (destroys the Float values) validPtr.deinitialize(count: swift2DArray[index].count) // Deallocate the memory block validPtr.deallocate() }
Scenario 2: Creating a Dynamic 2D Array Directly for the Framework
If you don’t have an existing Swift array and need to create a 2D array specifically for the function call, you can allocate memory directly:
// Define the dimensions your framework expects let numberOfSubArrays = 3 let elementsPerSubArray = 4 // Step 1: Allocate memory for the array of pointers let args = UnsafeMutablePointer<UnsafeMutablePointer<Float>?>.allocate(capacity: numberOfSubArrays) // Step 2: Allocate and initialize each subarray for i in 0..<numberOfSubArrays { let subPtr = UnsafeMutablePointer<Float>.allocate(capacity: elementsPerSubArray) // Initialize with default values (e.g., 0.0) or populate with custom data subPtr.initialize(repeating: 0.0, count: elementsPerSubArray) args[i] = subPtr } // Call the framework function yourFrameworkObject.applyFilters( input_image, input_params: input_params, output_image: output_image, output_params: output_params, filter_id: yourFilterID, args: args ) // Clean up memory for i in 0..<numberOfSubArrays { guard let validPtr = args[i] else { continue } validPtr.deinitialize(count: elementsPerSubArray) validPtr.deallocate() } args.deinitialize(count: numberOfSubArrays) args.deallocate()
Key Notes to Avoid Issues
- Memory Management: Swift does not automatically manage memory allocated with
allocate(), so you must always pairallocate()withdeallocate()andinitialize()withdeinitialize(). Forgetting this will cause memory leaks. - Array Lengths: Ensure the size of each subarray matches exactly what your Objective-C++ framework expects. Mismatched lengths can lead to crashes or undefined behavior.
- Nil Pointers: If your framework allows some entries in
argsto benil, you can simply appendniltopointerBufferor setargs[i] = nilin the dynamic allocation scenario. - Type Compatibility:
UnsafeMutablePointer<UnsafeMutablePointer<Float>>is implicitly convertible toUnsafeMutablePointer<UnsafeMutablePointer<Float>?>!since Swift’s optional pointers have the same memory layout as non-optional ones (as long as you don’t passnilwhere a non-nil pointer is required).
内容的提问来源于stack exchange,提问作者georgebp

