Python 中的 C _IOR 函数的等价物是啥?

Posted

技术标签:

【中文标题】Python 中的 C _IOR 函数的等价物是啥?【英文标题】:What is the equivalent of the C _IOR function in Python?Python 中的 C _IOR 函数的等价物是什么? 【发布时间】:2013-12-10 17:15:37 【问题描述】:

我最近在looking 处理一些 C 代码并“翻译”为 Python,但被一个名为 _IOR 的特定函数卡住了。它在sys/ioctl.h 中定义如下:

#define _IOC(inout,group,num,len) \
    (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num))
#define _IOR(g,n,t) _IOC(IOC_OUT,   (g), (n), sizeof(t))

我已经看到它以这些方式调用:

_IOR('t', 3, int)
_IOR('keys', 1, unsigned char *)

“keys”调用是我需要做的。看起来它正在对字符串进行按位运算。

我设法找到了与上述等效的 Python 代码,但它仅适用于单个字符。

_IOC_NRBITS   =  8
_IOC_TYPEBITS =  8
_IOC_SIZEBITS = 14
_IOC_DIRBITS  =  2

_IOC_NRSHIFT = 0
_IOC_TYPESHIFT =(_IOC_NRSHIFT+_IOC_NRBITS)
_IOC_SIZESHIFT =(_IOC_TYPESHIFT+_IOC_TYPEBITS)
_IOC_DIRSHIFT  =(_IOC_SIZESHIFT+_IOC_SIZEBITS)

_IOC_NONE = 0
_IOC_WRITE = 1
_IOC_READ = 2
def _IOC(direction,type,nr,size):
    return (((direction)  << _IOC_DIRSHIFT) |
        ((type) << _IOC_TYPESHIFT) |
        ((nr)   << _IOC_NRSHIFT) |
        ((size) << _IOC_SIZESHIFT))
def _IOR(type, number, size):
    return _IOC(_IOC_READ, type, number, size)

这适用于单字符调用。

_IOR(ord('t'), 3, 1)

但我不知道第二次调用'keys'的等价物。有没有办法在 Python 中执行以下 C 调用?

_IOR('keys', 1, unsigned char *)

【问题讨论】:

在第二个示例中,宏不是将某些堆栈常量“键”的地址或地址放入您的结果中吗?似乎宏不是为评估 char *...而构建的... 它肯定是在字符串键上做的,虽然我不确定如何;它甚至可以编译和运行!我链接到的线程中有一点背景;这是供应商提供的样本:link。它给了我一个神奇的数字 -444763391,我试图弄清楚如何而不是硬编码。 【参考方案1】:

'keys' 是一个整数字符常量(包含四个字符),其值由实现定义。您说 C 代码 _IOR('keys', 1, unsigned char *) 返回的值是 -444763391,即 4 字节十六进制数 0xE57D7301。由此我们可以得出结论,此实现从'k'&lt;&lt;24|'e'&lt;&lt;16|'y'&lt;&lt;8|'s' 计算'keys' 的整数值0x6B657973。 _IOR 值 0xE57D7301 来自表达式

2<<30|4<<16|'keys'<<8|1
:     :     :         :
:     :     :         1 = num n
:     :     'keys' = group g
:     4 = sizeof (unsigned char *)
2 = _IOC_READ

- 请注意,只有 8 位是为 TYPE(组)值保留的,而这种创造性地使用 32 位值会使 TYPE 溢出到 SIZE 和 DIR 位(与它们进行或运算)及其最高有效字节(由'k'&lt;&lt;24 产生)甚至被移出int 值。

使用您的 Python 函数,您可以通过调用计算相同的值

_IOR(ord('e')<<16|ord('y')<<8|ord('s'), 1, 4)

(因为k 丢失了,我们可以直接删除它)。

【讨论】:

【参考方案2】:

不能保证您在 char* 上运行所获得的数字是任何特定数字。在计算keys 的_IOR 时,宏将字符串的地址视为整数。结果将根据keys 在堆栈中的位置而变化。因此,在 Python 中这个功能确实没有很好的替代品。

来自docs for _IOR(g, n, t):

g 指定此 ioctl 类型所属的组。这个论点必须 是一个非负的 8 位数字(即,在 0-255 范围内)。 如果一个新的 ioctl 组,您可以将值零 (0) 传递给该参数 没有被定义。

该函数的预期用途是将一个字节作为第一个参数(通过字符或整数类型)。话虽这么说,“钥匙”可能被分配给某个随机组。我会选择一个你认为还没有被占用的组(或者在你的 C 代码中查找它当前分配到的组并使用该编号)来代替 keys

或者,您总是可以只取输入字符串的第一个字符并将其视为组 ID。

def _IOR(group, number, size):
    if isinstance(group, basestring):
        group = ord(group[0]) if group else 0
    return _IOC(_IOC_READ, group, number, size)

然后_IOR('t', 3, 1)_IOR('keys', 1, 1) 仍然会运行,尽管组分配与 C 宏不同。但由于该宏被滥用于 keys 分配,我认为这不会成为问题。

【讨论】:

此答案中的基本错误是将'keys' 视为字符串,但事实并非如此;它是一个包含多个字符的整数字符常量

以上是关于Python 中的 C _IOR 函数的等价物是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Python 习语“if __name__ == '__main__'”的 clojure 等价物是啥?

关于VC++的Winmain函数(WINAPI是啥?)

Matlab 的 tic 和 toc 函数的 Python 等价物是啥?

Excel 的 Beta 发行版的 Python 等价物是啥?

带有ndk平台错误帮助'_IOR'的c ++未在此范围内声明

Kotlin 中的 Python 列表、集合和映射推导等价物是啥?