首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >c_ulong重移位的C类型重新实现

c_ulong重移位的C类型重新实现
EN

Stack Overflow用户
提问于 2013-03-22 04:41:49
回答 1查看 2.1K关注 0票数 5

我正在通过ctype访问一个C库,并且遇到了以下问题:

我正在使用ctypeslib生成一个“包装器”(用于使用ctype访问库的ctype命令)。C库包含宏,在此步骤中将宏转换为python函数。(为了尽可能地独立于库内部,我想在python中使用其中的一些宏。)

其中一个宏如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# using the ctypes types
myuint16_t = c_ushort
myuint32_t = c_ulong

def mymacro(x): return (myuint16_t)((myuint32_t)(x) >> 16) # macro

我希望以以下方式(在函数中)使用独立模块中生成的函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
return wrapper.mymacro(valueToBeConverted) # valueToBeConverted is an int

但是,使用这一行,我得到了以下错误:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
....   
def mymacro(x): return (myuint16_t)((myuint32_t)(x) >> 16) # macro
TypeError: unsupported operand type(s) for >>: 'c_ulong' and 'int'

(我知道转移c_ulong的常用方法是c_ulongvar.value >> x,但是每当C库中发生变化时,我就必须修补生成的包装器。所以我尽量避免这种情况)。

这里似乎不能使用__rshift__的c_ulong实现。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
print c_ulong.__rshift__
# throws AttributeError: type object 'c_ulong' has no attribute '__rshift__'

嗯,看起来很奇怪..。因此,我决定重新实现c_ulong的c_ulong方法,以使其正常工作:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from ctypes import *
from types import MethodType

def rshift(self, val):
    print self.value >> val

# create an unbound method which applies to all (even existing) instances
c_ulong.__rshift__ = MethodType(rshift, None, c_ulong)

a = c_ulong(1)
a >> 16

但这并不能解决问题。我还在犯一个错误:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
a >> 16
TypeError: unsupported operand type(s) for >>: 'c_ulong' and 'int'

是否可能__rshift__方法只能用于同一类的两个实例?我尝试了以下几点:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def rshift(self, val):
    print self.value >> int(val.value)

a = c_ulong(1)
a >> c_ulong(16) 

而且起作用了。但这也意味着我仍然需要修补生成的包装器。

有人知道这里的诀窍是什么吗?

更新

@eryksun的解决方案奏效了。我正在使用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from ctypes import *
# from types import MethodType

def _rshift(self, other):
    if hasattr(other, 'value'):
        other = other.value
    return c_ulong(self.value >> other)

def _lshift(self, other):
    if hasattr(other, 'value'):
        other = other.value
    return c_ulong(self.value << other)

def _coerce(self, other):
    try:
        return self, self.__class__(other)
    except TypeError:
        return NotImplemented

# Add the functions to the type. A method is created when
# accessed as an attribute of an instance.
c_ulong.__lshift__ = _lshift
c_ulong.__rshift__ = _rshift
c_ulong.__coerce__ = _coerce
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-03-22 08:29:32

由于_ctypes._SimpleCData类型没有Py_TPFLAGS_CHECKTYPES标志,所以2.x子类被视为在二进制操作中使用__coerce__的旧样式数字。有关调用方案和函数binary_op1中的实现,请参见binary_op1

出于演示目的,可以将此标志切换到类型对象上,您只需将其定义(使用大量void *模糊地)到tp_flags字段。

黑客攻击PyTypeObject

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from ctypes import *
import _ctypes

Py_TPFLAGS_CHECKTYPES = 1 << 4

class PyTypeObject(Structure):
    _fields_ = (('ob_refcnt', c_ssize_t),
                ('ob_type', c_void_p),
                ('ob_size', c_ssize_t),
                ('tp_name', c_char_p),
                ('tp_basicsize', c_ssize_t),
                ('tp_itemsize', c_ssize_t),
                ('tp_dealloc', c_void_p),
                ('tp_print', c_void_p),
                ('tp_getattr', c_void_p),
                ('tp_setattr', c_void_p),
                ('tp_compare', c_void_p),
                ('tp_repr', c_void_p),
                ('tp_as_number', c_void_p),
                ('tp_as_sequence', c_void_p),
                ('tp_as_mapping', c_void_p),
                ('tp_hash', c_void_p),
                ('tp_call', c_void_p),
                ('tp_str', c_void_p),
                ('tp_getattro', c_void_p),
                ('tp_setattro', c_void_p),
                ('tp_as_buffer', c_void_p),
                ('tp_flags', c_long))

接下来,创建一个unsigned long子类,并使用from_address工厂为它创建一个PyTypeObject。使用内置id获取地址,这是特定于CPython的实现细节:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class c_ulong(_ctypes._SimpleCData):
    _type_ = "L"

    def __rshift__(self, other):
        print '__rshift__', self, other
        if hasattr(other, 'value'):
            other = other.value
        return c_ulong(self.value >> other)

c_ulong_type = PyTypeObject.from_address(id(c_ulong))

演示

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> a = c_ulong(16)
>>> b = c_ulong(2)

>>> a >> b
__rshift__ c_ulong(16L) c_ulong(2L)
c_ulong(4L)

>>> a >> 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for >>: 'c_ulong' and 'int'

最后一步如预期的失败了。现在设置旗子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> c_ulong_type.tp_flags |= Py_TPFLAGS_CHECKTYPES

>>> a >> 2
__rshift__ c_ulong(16L) 2
c_ulong(4L)

问题解决了?但那是个黑客。用__coerce__实现再试一次。

实现__coerce__

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class c_ulong(_ctypes._SimpleCData):
    _type_ = "L"

    def __rshift__(self, other):
        print '__rshift__', self, other
        if hasattr(other, 'value'):
            other = other.value
        return c_ulong(self.value >> other)

    def __coerce__(self, other):
        print '__coerce__', self, other
        try:
            return self, self.__class__(other)
        except TypeError:
            return NotImplemented

演示

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> a = c_ulong(16)
>>> b = c_ulong(2)

>>> a >> 2
__coerce__ c_ulong(16L) 2
__rshift__ c_ulong(16L) c_ulong(2L)
c_ulong(4L)

>>> 16 >> b
__coerce__ c_ulong(2L) 16
__rshift__ c_ulong(16L) c_ulong(2L)
c_ulong(4L)

当然,如果不能创建c_ulong,例如float,它就会失败。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> a >> 2.0
__coerce__ c_ulong(16L) 2.0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for >>: 'c_ulong' and 'float'
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15570610

复制
相关文章
plc的移位指令C语言实现,PLC中使用移位指令是如何实现移位动作的
楼主的意思大约是用X2来检测有没有罐子,X1用来定位灌装位置,现在需要把检测罐子的X2位置,移动到灌装位置的前面,应该是提供图片的下面的那种应用吧,
全栈程序员站长
2022/08/14
1.2K0
plc的移位指令C语言实现,PLC中使用移位指令是如何实现移位动作的
C 移位运算
移位运算分为左移(<<)与右移(>>),其中右移又分为逻辑右移与算术右移。三者实现如下: (1)左移:移出去的位丢弃,空缺位(vacant bit)用 0 填充; (2)逻辑右移:移出去的位丢弃,空缺位(vacant bit)用 0 填充; (3)算术右位:移出去的位丢弃,空缺位(vacant bit)用符号位来填充。
恋喵大鲤鱼
2019/07/01
2K0
C 移位运算
c语言移位操作
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/117843.html原文链接:https://javaforall.cn
全栈程序员站长
2022/07/14
1.4K0
plc的移位指令C语言实现,移位指令做流水灯-PLC中使用移位指令是如何实现移位动作的-电气资讯 – 电工屋…「建议收藏」
其中OPR用除立即数外的任何寻址方式。移位次数由CNT决定,在8086中可以是1或CL,CNT为1时只移一位;如果需要移位的次数大于1时,需要先将移位次数存入CL寄存器中,而移位指令中的CNT写为CL即可。在其他机型中可使用CL和CNT,且CNT的值除可用1外,还可以用8位立即数指定范围从1到31的移位次数。有关OPR和CNT的规定适用于以下所有指令操作。具体格式如下所述。以逻辑右移为例。
全栈程序员站长
2022/09/05
1.6K0
plc的移位指令C语言实现,移位指令做流水灯-PLC中使用移位指令是如何实现移位动作的-电气资讯 – 电工屋…「建议收藏」
C语言中的移位运算
移位运算包括左移和右移 左移运算: x<<k:x左移k位,并在右端补零。 右移运算: 逻辑右移: x>>k:x右移k位,并在左端补零。 算术右移: x>>k:x右移k位,并在左端补最高有效位的值。
全栈程序员站长
2022/09/14
1.5K0
C# - 为值类型重定义相等性
重写object.Equals()方法,是避免了反射,因为System.ValueType里面对object.Equals()方法的重写实现如下:
solenovex
2019/05/25
1.2K0
C# - 为引用类型重定义相等性
例如两个引用类型的变量 x 和 y,如果这样写:if(x == y) {...},那么大家都明白,这个比较的是引用的相等性。
solenovex
2019/05/25
7450
c语言中的位移位操作
能够自己实践实践阿。引用自:http://blog.chinaunix.net/u1/33888/showart_334911.html
全栈程序员站长
2022/07/12
6160
C语言实现进制转换、移位运算小工具
流程图 #include <stdio.h> #include <stdlib.h> #include <math.h> #include <conio.h> #include <stdarg.h> #include <ctype.h> #include "conversion.h" char MainMenu(); //主菜单 void pause(const char *str, ...); //暂停程序 void TransformMenu(); //进制转换菜单 void AddMenu(
程序员小涛
2022/05/07
8580
C语言实现进制转换、移位运算小工具
C# - 实现类型的比较
如果某个类型的实例需要与该类型的其它实例进行比较或者排序的话,那么该类型就可以通过实现IComparable<T>接口来达到此目的。
solenovex
2019/05/25
1K0
C++移位运算符
The behavior is undefined if the right operand is negative, orgreater than or equal to the length in bits of the promoted left operand.
全栈程序员站长
2022/07/15
6930
移位指令实现乘法
include irvine32.inc; .data i dword 0; sum qword 0; str1 byte “请输入16进制的(32位整数)乘数和被乘数”,0 str2 byte “乘积为:”,0; j dword 0;
全栈程序员站长
2022/09/05
3680
C# 移位运算符
int result1= 66 << 1;//正数的左移位运算规则,左移一位乘以2,右移移位除以2 左移两位乘以4,三位乘以8,4位乘以16,右移则相反; int result2 = -66<< 1; //负数的移位运算在最高位补1;运算规则和正数一样 Console.WriteLine("正数移位"+result1+"............"+"负数移位"+result2); 当声明重载C#移位运算符时,第一个操作数的类型必须总是
郑小超.
2018/01/24
9510
php去重后重新排键值
因为我们已经移除了一些元素,因此数组看起来不是正常的序列。比如我们可能会得到:array(0=>’A’,2=>’B’,5=>’C’);。在某些情况下,这不是一个问题,但是如果你需要数组的键值保持数字的序列,你可以使用一到两种方法解决键值乱序的问题。
黄啊码
2020/05/29
1.8K0
jz2440重新分区
在购买开发板的时候,板子上已经烧写好了bootloader、内核和文件系统。但是在具体使用时,发现板子上划分的内核分区只有2M,但是我编译出来的内核大于2M,于是将内核烧写到nandflash上面时会启动不成功。怎么办呢?查找资料后,找到了解决办法。 步骤如下 1,修改文件uboot-1.1.6/include/configs/100ask2440.h 如果是非jz2440开发板,找不到这个文件。不过大致路径没错,可以先使用以下命令搜索:
韦东山
2020/09/30
1K3
jz2440重新分区
单片机c语言循环移位指令,avr单片机中左移位和右移位指令
计算机的指令系统是一套控制计算机操作的代码,称之为机器语言。计算机只能识别和执行机器语言的指令。为了便于人们理解、记忆和使用,通常用汇编语言指令来描述计算机的指令系统。汇编语言指令可通过汇编器翻译成计算机能识别的机器语言。
全栈程序员站长
2022/08/23
1.8K0
C 语言中负数移位运算讲解
C 语言中负数移位运算讲解 “<<”、“>>”为移位运算符。 “<<”为左移位运算符,即数据字节中的每个二进制位同时 向左移位。如“x<<n”表示 x 中的每个二进制位同时向左移动 n 位。 “>>”为右移位运算 符,即数据字节中的每个二进制位同时向右移位。如“x>>n”表示 x 中的每个二进制位同时 向右移动 n 位。 下图演示了一个 2 字节变量左移 3 位的过程: 十进制数-555 的二进制表: 1 0 0 0 0 0 1 0 0 0 1 0 1 0 1 1 先转换成二进制补码表: 1 1 1 1 1 1 0 1 1 1 0 1 0 1 0 0 最左端位保持不变 补码加“1”后状态 再将补码加“1”: 1 1 1 1 1 1 0 1 1 1 0 1 0 1 0 1 下一步向左移 3 位: 1 1 1 0 1 1 1 0 1 0 1 0 1 0 0 0 左端“离开”3 位丢弃 右端“移入”3 位用“0”补齐 最左端一位保持不变 再转换成二进制补码表: 1 0 0 1 0 0 0 1 0 1 0 1 0 1 1 1 补码再加“1”: 到此步结束。 1 0 0 1 0 0 0 1 0 1 0 1 1 0 0 0 补码加“1”后状态 结果转换成十进制数为“- 4440”。 总结:负数左移时,任何情况下“移入”位将用“0”补齐。 “>>”右移位运算可分为两种情况:一种是移入“0”的叫逻辑右移;一种是移入“1”的叫 算术右移。 负数右移用到的是算术右移。 下图演示了一个 2 字节变量右移 3 位的过程: 十进制数-555 的二进制表: 1 0 0 0 0 0 1 0 0 0 1 0 1 0 1 1 先转换成二进制补码表: 1 1 1 1 1 1 0 1 1 1 0 1 0 1 0 0 最左端位保持不变 补码加“1”后状态 再将补码加“1”: 1 1 1 1 1 1 0 1 1 1 0 1 0 1 0 1 下一步向右移 3 位: 1 1 1 1 1 1 1 1 1 0 1 1 1 0 1 0 左端“移入”3 位用“1”补齐 右端“离开”3 位丢弃 最左端一位保持不变 再转换成二进制补码表: 1 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 补码再加“1”: 到此步结束。 1 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 补码加“1”后状态 结果转换成十进制数为“- 70”。 总结:负数右移时,任何情况下“移入”位将用“1”补齐。 注:二进制表最左端的二进制位表示符号位,“+”用“0”表示,“-”用“1”表示。
全栈程序员站长
2022/09/14
2.5K0
苏宁、国美2021重新出发
在2008年,国内的网民数量只有两亿上下,电商还没有成为人们的消费首选时,国美和苏宁算得上是零售领域中最强势的存在。但是在十几年后,不论是国美还是苏宁,都因为多方面的原因,而已然走下神坛。
刘旷
2021/04/08
3910
2009年重新设计过的著名的Logo
Logo设计的好坏,关系着一个企业如何树立形象的问题。Logo设计本身就是一个困难的课题,有了著名的Logo,将它重新设计就是一项更加挑战的工作。如果处理不当,他会带来怎样的后果?文中列出了2009年重新设计过的著名Logo,在这里不评判他们的好坏,只是列在这里,供大家来参考。
大江小浪
2018/07/25
3390
2009年重新设计过的著名的Logo
DS顺序表之循环移位 C++
顺序表的移位是循环移位,例如顺序表:1,2,3,4,5,6。如果左移1位,即原来的头元素移动到末尾,其它元素向左移1位,变成2,3,4,5,6,1。同理,如果右移1位,即原来的尾元素移动到头,其它元素向右移1位,变成6,1,2,3,4,5。以下是移位的多个例子:
叶茂林
2023/07/30
2580

相似问题

macOS上的Python c_ulong类型为64位

12

更改其他类中c_ulong()的值

11

C#中的快速数组移位实现?

65

使用Vlfeat的C API实现快速移位

14

带Pandas的移位间隔重采样

18
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文