用ctypes或pyObjc调用函数

时间:2018-08-15 16:17:17

标签: python macos pointers ctypes pyobjc

我想用Python调用IOKit框架。

这是我要调用的Objective-C函数的签名:

IOReturn IODisplayGetFloatParameter(io_service_t service, IOOptionBits options, CFStringRef parameterName, float *value);

使用pyObjc,在导入后,我将执行以下操作:

brightness = 0.0
IODisplayGetFloatParameter(service, 0, kIODisplayBrightnessKey, brightness)

但是,出现此错误:

ValueError: depythonifying 'pointer', got 'float'

这是BridgeSupport文件的相关位,pyObjc正在IOKit.IODisplayGetFloatParameter()上生成句柄:

<function name='IODisplayGetFloatParameter'>
<arg type='I'/>
<arg type='L' type64='I'/>
<arg type='^{__CFString=}'/>
<arg type='^f'/>
<retval type='i'/>

这使我相信我需要创建pyObjc对象,该对象表示一个指向float的指针,但是我很难找到相关的文档来做到这一点。

因此,我尝试使用ctypes,但是它存在段错误,因为我没有赋予它正确的argtypes或将正确的值传递给函数。

from ctypes import CDLL, c_void_p, byref, c_char_p, c_int, c_float, pointer, POINTER
from ctypes.utils import find_library

c_float_p = POINTER(c_float) 
float_ptr = c_float_p(c_float(0.0))
IOKit = CDLL(find_library('IOKit'))

IOKit.IODisplaySetFloatParameter.argtypes = [c_int, c_int, c_char_p, c_float_p]
IOKit.IODisplaySetFloatParameter(service_goes_here, 0, "brightness", float_pointer)
Segmentation fault: 11

谁能指出我的方向:

  1. 将浮点指针传递给pyObjc包装的函数吗?
  2. 使用ctypes呼叫IODisplayGetFloatParameter吗?

1 个答案:

答案 0 :(得分:0)

这里的问题是网桥支持文件不完整(可悲的是,大多数系统网桥支持文件都不够)。

以下代码更有效地展示了此功能:

import objc

bundle = objc.loadBundle('IOKit', bundle_path='/System/Library/Frameworks/IOKit.framework', module_globals=globals())
objc.objc.loadBundleFunctions(bundle, globals(), [
    (
        'IODisplayGetFloatParameter',
        objc._C_INT + objc._C_UINT + objc._C_NSUInteger + objc._C_ID + objc._C_PTR + objc._C_FLT,
        '',
        { 'arguments': { 3: { 'type_modifier': b'n' }}} ),
])
print(IODisplayGetFloatParameter.__metadata__())

这假定IODisplayGetFloatParameter通过引用返回单个浮点值。

另请参阅:https://pythonhosted.org/pyobjc/metadata/manual.html