Maybe I'm the first person doing this in Swift but there seems to be nothing on the net using &/inout together with uint8_t in Swift. Could someone translate this please? Is this relationship bitwise?
Objective-C
uint8_t *buf=(uint8_t *) CVPixelBufferGetBaseAddress(cvimgRef);
Swift attempt
let inout buf:uint8_t = SOMETHING HERE CVPixelBufferGetBaseAddress(cvimgRef)
CVPixelBufferGetBaseAddress() returns a UnsafeMutablePointer<Void>,
which can be converted to an UInt8 pointer via
let buf = UnsafeMutablePointer<UInt8>(CVPixelBufferGetBaseAddress(pixelBuffer))
Update for Swift 3 (Xcode 8), Checked for Swift 5 (Xcode 11):
if let baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer) {
let buf = baseAddress.assumingMemoryBound(to: UInt8.self)
// `buf` is `UnsafeMutablePointer<UInt8>`
} else {
// `baseAddress` is `nil`
}
Related
I was trying to port the following Swift code to Objective-C:
var contextImage: UIImage? = ...
let image: CGImage? = contextImage?.cgImage
let dataProvider: CGDataProvider? = image?.dataProvider
let data: CFData? = dataProvider?.data
let baseAddress = CFDataGetBytePtr(data!)
contextImage = nil
let unmanagedData = Unmanaged<CFData>.passRetained(data!)
var pixelBuffer: CVPixelBuffer?
let status = CVPixelBufferCreateWithBytes(nil,
(image?.width)!,
(image?.height)!,
kCVPixelFormatType_32BGRA,
UnsafeMutableRawPointer( mutating: baseAddress!),
(image?.bytesPerRow)!,
{ releaseContext, baseAddress in
let contextData = Unmanaged<CFData>.fromOpaque(releaseContext!)
contextData.release()
},
unmanagedData.toOpaque(),
nil,
&pixelBuffer)
but I got stuck at the Unmanaged section and was not able to find the proper Objective-C way of doing that under ARC (the documentation of Unmanaged seems to exist only for Swift):
CGImageRef image = contextImage.CGImage;
CGDataProviderRef dataProvider = CGImageGetDataProvider(image);
CFDataRef data = CGDataProviderCopyData(dataProvider);
const UInt8 * baseAddress = CFDataGetBytePtr(data);
contextImage = nil;
// ... now what?
Eventually I accomplished it by integrating a Swift file into the Objective-C project but I still wonder, what is the proper way of porting that original Swift code in Objective-C?
I don't think you need Unmanaged. Even in the Swift documentation for this function RawPointers are used.
This is how the documentation looks like for the ObjC.
CVReturn CVPixelBufferCreateWithBytes (CFAllocatorRef allocator,
size_t width,
size_t height,
OSType pixelFormatType,
void *baseAddress,
size_t bytesPerRow,
CVPixelBufferReleaseBytesCallback releaseCallback,
void *releaseRefCon,
CFDictionaryRef pixelBufferAttributes,
CVPixelBufferRef *pixelBufferOut);
Its implementation could look something like this.
CVPixelBufferRef pixelBuffer = NULL;
cvErr = CVPixelBufferCreateWithBytes(kCFAllocatorDefault,
FRAME_WIDTH,
FRAME_HEIGHT,
kCVPixelFormatType_32BGRA,
(void*)CFDataGetBytePtr(imageData),
CGImageGetBytesPerRow(image),
NULL,
NULL,
NULL,
&pixelBuffer);
More in documentation for CVPixelBufferCreate.
This answer and this answer both show how to set TCP_NODELAY for NSOutputStream in Objective-C. I need some help on getting this to work in Swift, and I believe that it's probably just a mistake I'm making with the API.
This is the Objective-C solution that supposedly works:
CFDataRef nativeSocket = CFWriteStreamCopyProperty(`myWriteStream`, kCFStreamPropertySocketNativeHandle);
CFSocketNativeHandle *sock = (CFSocketNativeHandle *)CFDataGetBytePtr(nativeSocket);
setsockopt(*sock, IPPROTO_TCP, TCP_NODELAY, &(int){ 1 }, sizeof(int));
CFRelease(nativeSocket);
This is my attempt at translating it into Swift:
let nativeSocket: CFDataRef = CFWriteStreamCopyProperty(myWriteStream, kCFStreamPropertySocketNativeHandle).data
let sock = CFSocketNativeHandle(CFDataGetBytePtr(nativeSocket).memory)
var one = Int(1)
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &one, UInt32(sizeofValue(one)))
The real issue is getting a CFDataRef from myWriteStream (an NSOutputStream), and then getting a CFSocketNativeHandle from that. In the Swift code above, it always crashes on the first line while trying to create nativeSocket (specifically, trying to access the data property).
Can somebody help me out with this?
Ok, so after a while I figured it out. Here's the working code in case somebody else needs it:
let socketData = CFWriteStreamCopyProperty(self.outputStream!, kCFStreamPropertySocketNativeHandle) as! CFData
let handle = CFSocketNativeHandle(CFDataGetBytePtr(socketData).memory)
var one: Int = 1
let size = UInt32(sizeofValue(one))
setsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &one, size)
Im trying to do the following in Swift:
CFArrayRef attachmentsArray = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, 0);
if (CFArrayGetCount(attachmentsArray)) {
CFBooleanRef notSync;
CFDictionaryRef dict = CFArrayGetValueAtIndex(attachmentsArray, 0);
BOOL keyExists = CFDictionaryGetValueIfPresent(dict,
kCMSampleAttachmentKey_NotSync,
(const void **)¬Sync);
I have:
if CFArrayGetCount(attachmentsArray) != 0 {
let dict = CFArrayGetValueAtIndex(attachmentsArray, 0)
However, dict is a UnsafePointer instead of a dictionary like it should be. When I printed attachmentsArray I got
Optional({ DependsOnOthers = 0; })
I tried casting it to a CFDictionaryRef but it would fail in runtime.
How do I succeed in doing the above Obj-C code in Swift?
However, dict is a UnsafePointer instead of a dictionary like it should be.
No, not "like it should be". Look at the declaration:
func CFArrayGetValueAtIndex(theArray: CFArray!, _ idx: CFIndex)
-> UnsafePointer<Void>
It returns an UnsafePointer-to-void because that is what it is supposed to do. (In Objective-C it returns a const void *.)
I'm trying to capture a window list in a Mac OS X app using Swift. The CGWindowListCreateImageFromArray function requires a CFArray. I've tried several things and this is the closest I've got. Or is there a better way to convert the array?
import Cocoa
// Example swift array of CGWindowID's
var windowIDs = [CGWindowID]();
windowIDs.append(1);
windowIDs.append(2);
// Convert to CFArray using CFArrayCreate
let allocator = kCFAllocatorDefault
let numValues = windowIDs.count as CFIndex
let callbacks: UnsafePointer<CFArrayCallBacks> = nil
var values: UnsafeMutablePointer<UnsafePointer<Void>> = nil
/* how do I convert windowIDs to UnsafeMutablePointer<UnsafePointer<Void>> for the values? */
let windowIDsCFArray = CFArrayCreate(allocator, values, numValues, callbacks);
let capture = CGWindowListCreateImageFromArray(CGRectInfinite, windowIDsCFArray, CGWindowImageOption(kCGWindowListOptionOnScreenOnly));
You can initialize your UnsafeMutablePointer with your array so long as you set your CGWindowIDs to CFTypeRef:
var windows: [CFTypeRef] = [1, 2]
var windowsPointer = UnsafeMutablePointer<UnsafePointer<Void>>(windows)
var cfArray = CFArrayCreate(nil, windowsPointer, windows.count, nil)
Converted Ian's answer to Swift 4:
let windows = [CGWindowID(17), CGWindowID(50), CGWindowID(59)]
let pointer = UnsafeMutablePointer<UnsafeRawPointer?>.allocate(capacity: windows.count)
for (index, window) in windows.enumerated() {
pointer[index] = UnsafeRawPointer(bitPattern: UInt(window))
}
let array: CFArray = CFArrayCreate(kCFAllocatorDefault, pointer, windows.count, nil)
let capture = CGImage(windowListFromArrayScreenBounds: CGRect.infinite, windowArray: array, imageOption: [])!
let image: NSImage = NSImage(cgImage: capture, size: NSSize.zero)
Swift.print(image)
Arrays in Swift are bridged to NSArray, given they contain objects, e.g., conform to [AnyObject] type. Since CGWindowID is a UInt32, you need to convert it to NS family, array's map() method is an elegant approach.
var windows: [CGWindowID] = [CGWindowID(1), CGWindowID(2)]
var array: CFArray = windows.map({NSNumber(unsignedInt: $0)}) as CFArray
This, however, doesn't reflect on the actual CGWindowListCreateImageFromArray problem. Here's the working solution for that:
let windows: [CGWindowID] = [CGWindowID(17), CGWindowID(50), CGWindowID(59)]
let pointer: UnsafeMutablePointer<UnsafePointer<Void>> = UnsafeMutablePointer<UnsafePointer<Void>>.alloc(windows.count)
for var i: Int = 0, n = windows.count; i < n; i++ {
pointer[i] = UnsafePointer<Void>(bitPattern: UInt(windows[i]))
}
let array: CFArray = CFArrayCreate(kCFAllocatorDefault, pointer, windows.count, nil)
let capture: CGImage = CGWindowListCreateImageFromArray(CGRectInfinite, array, CGWindowImageOption.Default)!
let image: NSImage = NSImage(CGImage: capture, size: NSZeroSize)
Swift.print(image) // <NSImage 0x7f83a3d16920 Size={1440, 900} Reps=("<NSCGImageSnapshotRep:0x7f83a3d2dea0 cgImage=<CGImage 0x7f83a3d16840>>")>
I'm not great at ObjC, please correct if wrong, but from what I understand by playing with the SonOfGrab example and particular piece of code below is that the final pointer structure contains window ids (UInt32) not inside the memory cell (memory property of UnsafePointer instance), but inside memory address (hashValue property).
const void *windowIDs[2];
windowIDs[0] = 10;
windowIDs[1] = 20;
It's interesting, since values aren't stored in the memory, but inside the address descriptors, with oldest architectures being 32-bit UInt32 values fit perfectly into address pointers. Perhaps back in the days when the memory was a limiting factor this made a lot of sense and was a great approach. Discovering this all night in Swift in 2016 made me suicidal.
What's worse it fails in Xcode 7.2 playground with certain window ids, probably because of the way it handles memory, but works in the actual app.
I am creating a project in Swift. I want to display the modelName. I am following below link to get the modelName
http://myiosdevelopment.blogspot.co.uk/2012/11/getting-device-model-number-whether-its.html
The code in the link is written in objective-c. But I am not sure how to import this in Swift.
#import <sys/utsname.h>
Please someone help
sys/utsname.h is imported into Swift by default, so you don't really need to import it from the bridging header. But using utsname from Swift is really painful though, as Swift imports fixed length C array as tuples. If you look into utsname.h, you see that the C struct members of utsname are all char array of 256 length:
#define _SYS_NAMELEN 256
struct utsname {
char sysname[_SYS_NAMELEN]; /* [XSI] Name of OS */
char nodename[_SYS_NAMELEN]; /* [XSI] Name of this network node */
char release[_SYS_NAMELEN]; /* [XSI] Release level */
char version[_SYS_NAMELEN]; /* [XSI] Version level */
char machine[_SYS_NAMELEN]; /* [XSI] Hardware type */
};
Which gets imported into Swift like this:
var _SYS_NAMELEN: Int32 { get }
struct utsname {
var sysname: (Int8, Int8, /* ... 254 more times "Int8, " here ... */) /* [XSI] Name of OS */
var nodename: (Int8, Int8, /* ... snip ... */ ) /* [XSI] Name of this network node */
var release: (Int8, Int8, /* ... snip ... */ ) /* [XSI] Release level */
var version: (Int8, Int8, /* ... snip ... */ ) /* [XSI] Version level */
var machine: (Int8, Int8, /* ... snip ... */ ) /* [XSI] Hardware type */
}
Yes, they're tuples with 256 Int8s. Which cases this hilarious autocompletion in Xcode:
Currently, there is no way to initialize an tuple in Swift without writing out all value, so initializing it as a local variable would be rather verbose, as you see above. There is also no way to convert the tuple to an array, so that huge tuple is also not very useful.
The easiest solution would be to implement it in Objective-C.
If you're dead set on using Swift, you can do this, but it's not pretty:
// Declare an array that can hold the bytes required to store `utsname`, initilized
// with zeros. We do this to get a chunk of memory that is freed upon return of
// the method
var sysInfo: [CChar] = Array(count: sizeof(utsname), repeatedValue: 0)
// We need to get to the underlying memory of the array:
let machine = sysInfo.withUnsafeMutableBufferPointer { (inout ptr: UnsafeMutableBufferPointer<CChar>) -> String in
// Call uname and let it write into the memory Swift allocated for the array
uname(UnsafeMutablePointer<utsname>(ptr.baseAddress))
// Now here is the ugly part: `machine` is the 5th member of `utsname` and
// each member member is `_SYS_NAMELEN` sized. We skip the the first 4 members
// of the struct which will land us at the memory address of the `machine`
// member
let machinePtr = advance(ptr.baseAddress, Int(_SYS_NAMELEN * 4))
// Create a Swift string from the C string
return String.fromCString(machinePtr)!
}
In Swift 4 you can just use the UIDevice model property:
func getPhoneModel() -> String {
return UIDevice.current.model
}
my 2 cents for Swift 5 if You want to call utsname:
func platform() -> String {
var systemInfo = utsname()
uname(&systemInfo)
let size = Int(_SYS_NAMELEN) // is 32, but posix AND its init is 256....
let s = withUnsafeMutablePointer(to: &systemInfo.machine) {p in
p.withMemoryRebound(to: CChar.self, capacity: size, {p2 in
return String(cString: p2)
})
}
return s
}
The code shown in that blog post looks like C and not Objective C - however I think you can write a wrapper around that in Objective-C
In order to enable bridging between Objective-C and swift just add a new Objective-C file to your project - Xcode will prompt you whether to create a bridging header
Just answer yes, and Xcode will automatically create a <appname>-Bridging-Header.h file. Open it and #include any objective-c header file that you want to use from swift.
In swift 2.0:
var sysInfo: [CChar] = Array(count: sizeof(utsname), repeatedValue: 0)
let deviceModel = sysInfo.withUnsafeMutableBufferPointer { (inout ptr: UnsafeMutableBufferPointer<CChar>) -> String in
uname(UnsafeMutablePointer<utsname>(ptr.baseAddress))
let machinePtr = ptr.baseAddress.advancedBy(Int(_SYS_NAMELEN * 4))
return String.fromCString(machinePtr)!
}
print(deviceModel)