首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >快速的“数组”内存分配,加上切换显示镜像

快速的“数组”内存分配,加上切换显示镜像
EN

Stack Overflow用户
提问于 2016-06-07 22:27:07
回答 2查看 544关注 0票数 1

注:见以下修改后的员额:硬件镜像

我编写了两个Swift函数,用于切换OSX中的显示镜像。两者都能工作;它们之间的区别只是处理指针时的语法。为了方便那些有兴趣学习如何在Swift中切换镜像的人,我在下面包含了操场文件的文本。

我的问题是内存分配。以下是感兴趣的部分:

toggleMirroringUgly

代码语言:javascript
复制
    // allocate space for array
    let displayListPtr = displayIDListPtr.alloc(Int(displayCount)) //see typealias above
    // fill the list
    postError(CGGetActiveDisplayList(displayCount, displayListPtr, &activeCount))

toggleMirroring

代码语言:javascript
复制
    // allocate space for list of displays
    var displayIDList = Array<CGDirectDisplayID>(count: Int(displayCount), repeatedValue: kCGNullDirectDisplay)
    // fill the list
    postError(CGGetActiveDisplayList(displayCount, &displayIDList, &activeCount))

CGGetActiveDisplayList是一个低级函数调用,它依赖于将数据安排在连续的内存位置上。我有理由相信,丑陋版本中的“alloc”是连续的。从经验上看,“数组”(…)调用也是连续的,但我是否可以依赖于始终为真(例如,如果显示的数量增加)?这种假设是关于Swift数组初始化器糟糕的形式吗?

下面是所有的代码;对格式化问题表示歉意。请注意,应该只调用这两个函数中的一个;否则,您将结束您开始的位置。

代码语言:javascript
复制
//: Playground - noun: a place where people can play

import Cocoa

// apparently not defined in Swift version of SDK 10.11 (XCode 7.3.1), so add manually
let kCGNullDirectDisplay = CGDirectDisplayID(0)
let kCGDirectMainDisplay = CGMainDisplayID()        // not used here, just for the record

let maxDisplays:UInt32 = 20    // not used
var onlineCount:UInt32 = 0     // not used

func postError(error : CGError){
    if error != CGError.Success {
        print("got an error")
    }
}


// this toggles all active displays, online or not
func toggleMirroring(){
    var displayCount:UInt32 = 0
    var activeCount:UInt32 = 0
    //var onlineCount:UInt32 = 0      //not used

    //get count of active displays (by passing nil to CGGetActiveDisplayList
    postError(CGGetActiveDisplayList(0, nil, &displayCount))

    if displayCount < 2 { return }  // no point in any mirroring functions

    //***
    // allocate space for list of displays
    var displayIDList = Array<CGDirectDisplayID>(count: Int(displayCount), repeatedValue: kCGNullDirectDisplay)

    // fill the list
    postError(CGGetActiveDisplayList(displayCount, &displayIDList, &activeCount))
    //***

    // determine if mirroring is active
    // hack to convert from boolean_t (aka UInt32) to swift's bool
    let displaysMirrored = CGDisplayIsInMirrorSet(CGMainDisplayID()) != 0

    // set master based on current mirroring state
    // if mirroring, master = null, if not, master = main display
    let master = (true == displaysMirrored) ? kCGNullDirectDisplay : CGMainDisplayID()

    // start the configuration
    var configRef:CGDisplayConfigRef = nil  //swift 3 syntax

    postError(CGBeginDisplayConfiguration(&configRef));

    for i in 0..<Int(displayCount) {
        let currentDisplay = CGDirectDisplayID(displayIDList[i])
        if CGMainDisplayID() != currentDisplay {
        CGConfigureDisplayMirrorOfDisplay(configRef, currentDisplay, master);
        }
    }

    if (false){     // change to true in order to execute the toggle
        postError(CGCompleteDisplayConfiguration (configRef,CGConfigureOption.Permanently))
    }

// The first entry in the list of active displays is the main display. In case of mirroring, the first entry is the largest drawable display or, if all are the same size, the display with the greatest pixel depth.
// The "Permanently" option might not survive reboot when run from playground, but does when run in an application
}

func toggleMirroringUgly(){
// just to decrease eye strain
typealias displayIDListPtr = UnsafeMutablePointer<CGDirectDisplayID>
typealias configurationRefPtr = UnsafeMutablePointer<CGDisplayConfigRef>

//get count of active displays (by passing nil to CGGetActiveDisplayList
postError(CGGetActiveDisplayList(0, nil, &displayCount))

if displayCount < 2 { return }  // no point in any mirroring functions

// ***
// allocate space for array
let displayListPtr = displayIDListPtr.alloc(Int(displayCount)) //see typealias above
// fill the list
postError(CGGetActiveDisplayList(displayCount, displayListPtr, &activeCount))
// ***

// determine if mirroring is active
// hack to convert from boolean_t (aka UInt32) to swift's bool
let displaysMirrored = CGDisplayIsInMirrorSet(CGMainDisplayID()) != 0
// set master based on current mirroring state
// if mirroring master = null, if not, master = main display
let master = (true == displaysMirrored) ? kCGNullDirectDisplay : CGMainDisplayID()

// make room for the configuration reference
let configRefPtr = configurationRefPtr.alloc(1)     //see typealias above
// start the configuration
postError(CGBeginDisplayConfiguration (configRefPtr));

for i in 0..<displayCount {
    let currentDisplay = CGDirectDisplayID(displayListPtr[Int(i)])
    if CGMainDisplayID() != currentDisplay {
        CGConfigureDisplayMirrorOfDisplay(configRefPtr[0], currentDisplay, master);
    }
}

if (false){         //change to true in order to flip the mirroring
    // make it happen
    postError(CGCompleteDisplayConfiguration (configRefPtr[0],CGConfigureOption.Permanently));
}
// The first entry in the list of active displays is the main display. In case of mirroring, the first entry is the largest drawable display or, if all are the same size, the display with the greatest pixel depth.
// The "Permanently" option might not survive reboot when run from playground, but does when run in an application
}


toggleMirroring()
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-01-11 08:29:42

我用新的显卡和NVIDIA驱动程序升级了我的电脑,发现上面的代码不再完全工作--打开镜像,但不关闭。显然,驱动程序可以选择使用硬件或软件镜像,这会改变编码。我在下面贴出一份修订本。

它只在我的系统(10.12.2)和卡(GTX980Ti)上进行过测试,但我认为逻辑也应该适应软件镜像和最近的操作系统版本。如果您有两个以上的显示,您可能可以修改它,通过英勇的努力,以反映任意组合。我的代码只会镜像所有其他的主显示器(或软件镜像中的最低的rez显示器)。

尽管jbandes的备注re: ContiguousArray是信息丰富的,但在这种情况下它不起作用-参见代码中的注释。此代码假定分配的UInt32s数组将是连续的。(对malloc和铸件来说,工作量太大了,但这还没有准备好生产。)

祝两位感兴趣的人好运!

代码语言:javascript
复制
//: Playground - noun: a place where people can play
import Cocoa
import Foundation

func postError(_ error : CGError){
    if error != CGError.success {
        print("got an error")
    }
}

func disableHardwareMirroring(){
    // designed for hardware mirroring with > 1 display
    // should be no penalty for running with only 1 display, using either hardware or software mirroring drivers
    // but not tested

    // start the configuration
    var configRef:CGDisplayConfigRef? = nil
    postError(CGBeginDisplayConfiguration(&configRef))

    // only interested in the main display
    // kCGNullDirectDisplay parameter disables hardware mirroring
    CGConfigureDisplayMirrorOfDisplay(configRef, CGMainDisplayID(), kCGNullDirectDisplay)

    // may not be permanent between boots using Playgroud, but is in an application
    postError(CGCompleteDisplayConfiguration (configRef,CGConfigureOption.permanently))
}

func toggleMirroring(){
    var displayCount:UInt32 = 0
    var activeCount:UInt32 = 0      //used as a parameter, but value is ignored
    //var onlineCount:UInt32 = 0    //not used

    //get count of active displays (by passing nil to CGGetActiveDisplayList
    postError(CGGetActiveDisplayList(0, nil, &displayCount))

    if displayCount == 1 {
        // either it's hardware mirroring or who cares?
        disableHardwareMirroring()
        return
    }

    // allocate space for list of displays
    // tried to use ContiguousArray, but CGGetActiveDisplayList requires Array<CGDirectDisplayID> parameter
    // ContiguousArrays cannot be typecast to Arrays (at least not easily)

    var displayIDList = Array<CGDirectDisplayID>(repeating: kCGNullDirectDisplay, count: Int(displayCount))

    // fill the list
    postError(CGGetActiveDisplayList(displayCount, &(displayIDList), &activeCount))


    // determine if mirroring is active (only relevant for software mirroring)
    // hack to convert from boolean_t (aka UInt32) to swift's bool
    let displaysMirrored = CGDisplayIsInMirrorSet(CGMainDisplayID()) != 0

    // set master based on current mirroring state
    // if mirroring, master = null, if not, master = main display
    let master = (true == displaysMirrored) ? kCGNullDirectDisplay : CGMainDisplayID()

    // start the configuration
    var configRef:CGDisplayConfigRef? = nil

    postError(CGBeginDisplayConfiguration(&configRef))

    for i in 0..<Int(displayCount) {
        let currentDisplay = CGDirectDisplayID(displayIDList[i])
        if CGMainDisplayID() != currentDisplay {
            CGConfigureDisplayMirrorOfDisplay(configRef, currentDisplay, master)
        }
    }

    postError(CGCompleteDisplayConfiguration (configRef,CGConfigureOption.permanently))

    // The first entry in the list of active displays is the main display. In case of mirroring, the first entry is the largest drawable display or, if all are the same size, the display with the greatest pixel depth.
    // The "Permanently" option might not survive reboot when run from playground, but does when run in an application
}


if (false) {  // change to true to run the code, false to edit
    toggleMirroring()
}
票数 1
EN

Stack Overflow用户

发布于 2016-06-08 00:10:14

数组不一定使用连续存储。有一个ContiguousArray类型,如果您有此倾向,您可以使用它,但是您仍然需要处理对CGGetActiveDisplayList的最后调用后返回的最大大小和实际大小之间的可能差异。

清除这种情况的一种方法可能是为Array定制一个方便的初始化程序:

代码语言:javascript
复制
extension Array {

    init<Size: IntegerType>(
        fillingBufferOfSize maxSize: Size,
        @noescape fillBuffer: (buffer: UnsafeMutablePointer<Element>, count: inout Size) throws -> ()) rethrows
    {
        let maxSizeAsInt = Int(maxSize.toIntMax())
        let buf = UnsafeMutablePointer<Element>.alloc(maxSizeAsInt)
        defer { buf.dealloc(maxSizeAsInt) }

        var actualCount: Size = 0
        try fillBuffer(buffer: buf, count: &actualCount)

        self.init(UnsafeBufferPointer(start: buf, count: Int(actualCount.toIntMax())))
    }

}

那么您可以使用Array(fillingBufferOfSize: ...)

代码语言:javascript
复制
var maxActive: UInt32 = 0
CGGetActiveDisplayList(0, nil, &maxActive)

let displays = Array(fillingBufferOfSize: maxActive) { (buffer, count) in
    CGGetActiveDisplayList(maxActive, buffer, &count)
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37690426

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档