- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
好的,听我说完;这个问题并不像您想象的那么愚蠢。
首先,一些背景知识:我最近开始使用 ctypes 模块,作为一项技术测试,我想使用 pygame 和 ctypes 编写一个 Mandelbrot 资源管理器,分别用于事件处理和访问 Mandelbrot 计算 dll。我最初的计划是通过让 Mandelbrot 函数计算和存储字符数组中整行像素的值并返回指向该数组的指针来最小化 ctypes 包装器开销:
Mandelbrot.restype = c_char_p
#...
str_location = Mandelbrot(x)
row = str_location.value
但事实证明这并没有真正起作用。 value 方法有两个缺陷:它会降低性能,因为它将 C 字符串逐字节复制到 python 字符串中,并且它不知道字符串的预期长度,因此数据中的任何零都将被视为空终止符,导致任何进一步的数据丢失。
我的第一个行动方案是拼凑一个快速 DLL,允许我反汇编一些 Python 对象。它有以下两个功能:
#define DLLINFO extern "C" __declspec(dllexport)
DLLINFO char show_char(char *p)
{
return *p;
}
DLLINFO void mov(char *p, char payload)
{
*p = payload;
}
我还将 show_char 函数封装在一个 Python 函数 show_object 中,该函数使用 sys.getsizeof 来打印 Python 对象的内存内容。拆开绳子后发现一个非常简单的设计:
>>> from hack import *; import sys
>>>
>>> #string experiment
>>> a = '01234567'
>>> hex(sys.getrefcount(a))
'0x3'
>>> hex(id(type(a)))
'0x1e1d81f8'
>>> hex(len(a))
'0x8'
>>> show_object(a)
3 2 1 0 byte
0 0 0 4 0 #reference count (+1 temporary reference)
1e 1d 81 f8 4 #pointer to type
0 0 0 8 8 #length
94 b b6 98 12 #???
0 0 0 1 16 #???
33 32 31 30 20 #Data '0123' (little endian)
37 36 35 34 24 #Data '4567'
0 28 #Null terminator
>>> #sys.getsizeof reported 29 bytes for 9 bytes of data.
(后面添加的数据注释)
我尝试用可变字节数组替换字符串,然后反汇编字节数组以查看应该将 Mandelbrot 数据写入何处:
>>> #bytearray experiment
>>> b = bytearray('01234567')
>>> hex(sys.getrefcount(b))
'0x2'
>>> hex(id(type(b)))
'0x1e1e5e20'
>>> hex(len(b))
'0x8'
>>> show_object(b)
3 2 1 0 byte
0 0 0 3 0 #reference count (+1 temporary reference)
1e 1e 5e 20 4 #pointer to type
0 0 0 8 8 #length
0 0 0 0 12 #???
0 0 0 9 16 #???
2 3a 63 a0 20 #???
2 92 93 38 24 #???
2 91 e4 90 28 #???
1 32 #???
>>> #sys.getsizeof reported 33 bytes for 8 bytes of data
好吧,我不知道数据在字节数组中的位置,所以没有骰子。
我的下一个计划是将字符串替换为 ctypes 内置的可变字符串,即 create_string_buffer。
>>> #buffer experiment
>>> from ctypes import *
>>> c = create_string_buffer('01234567')
>>> hex(id(type(c)))
'0x1ceb778'
>>> show_object(c)
3 2 1 0 byte
0 0 0 3 0 #reference count
1 ce b7 78 4 #pointer to type
2 38 f7 38 8 #???
0 0 0 1 12 #Here be dragons
0 0 0 0 16 #etc.
0 0 0 9 20
0 0 0 9 24
0 0 0 0 28
0 0 0 0 32
0 0 0 0 36
33 32 31 30 40 #data '0123'
37 36 35 34 44 #data '4567'
0 0 0 0 48
0 0 0 0 52
0 0 0 0 56
0 0 0 0 60
2 38 f8 40 64
2 38 f7 a0 68
ff ff ff fe 72
0 2e 0 65 76
>>> #sys.getsizeof reported 80 bytes for 9 bytes of data.
嗯。至少数据在某处。不幸的是,这个对象过于冗长而不实用。此外,它不是内置类型,所以我很难让它与其他函数一起使用。这是我决定切换回字符串并运行一些修改字符串的谨慎测试的时候:
>>> from hack import *
>>> s = "Hello, world!"
>>> show_object(s)
3 2 1 0 byte
0 0 0 3 0
1e 1d 81 f8 4
0 0 0 d 8
8f 8d ce 9c 12
0 0 0 0 16
6c 6c 65 48 20
77 20 2c 6f 24
64 6c 72 6f 28
0 21 32
>>> mov(id(s)+32, 63)
>>> print s
Hello, world?
>>> mov(id(s)+8,5)
>>> print s
Hello
到目前为止一切顺利。至少我这样做的几次都没有崩溃。事实上,即使将长度修改为较低的值也不会立即导致任何问题。 (虽然我不打算这样做)那么,为什么我在布置显示字符串可变的数据后问这个问题?
首先,我知道硬件有可能将字符串标记为不可变,并且尝试修改它们可能会导致段错误或类似问题:
char good_string[80];
good_string[8] = '!'; //Everything's okay so far.
char* bad_string = "This string's made out of const chars, beware!";
bad_string[8] = '!'; //And now you've got segfault!
其次,也是更重要的一点,我对 Python 的内部工作原理了解不够,无法自信地绕过 Python 对字符串的锁定并玩弄未定义的行为。现在,我很容易说服自己 Python FAQ 中关于字符串不可变的原因是错误的(我没有改变字符串的大小,而且字符串不像整数那样是基本的。),但我不知道是否有一些隐藏的原因字符串不应该被修改,如果我尝试做我计划做的事情,某些东西会在我脸上爆炸。这是我提交这个问题的主要原因;希望有知识的大神不吝赐教。
谢谢,您阅读了整个问题。对不起,简洁不是我的强项。 :)
最佳答案
有些计算机系统可以在硬件级别将任意范围的内存标记为只读,但这不是 python 中发生的情况。正在发生的事情是,根据定义,python 防止字符串在创建的位置被更改。
是的 - 通过更改 python 代码或提供新的内置函数,编写允许字符串在某些情况下可变的代码是完全可能的,但是如果您尝试使用可变的,您将遇到真正的困难例如,字符串作为字典键,并且清楚地给出了字符串的存储方式,改变长度会很困难(如果在大多数情况下不是不可能的话 - 你需要在当前字符串之后立即释放内存以便扩展到例如)。
请记住,即使使用可能称为直接内存访问的语言(例如 C),它的字符串也仅在某些情况下可变:您可以更改特定字符,但不能任意延长一个 C 字符串,既没有为它预留内存,也没有在每次更改时更改它的标识(如果你对它有多个引用,那么你就会遇到问题)。
关于python - python 字符串实际上在硬件级别上是不可变的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28020935/
我刚刚意识到二进制编译器会将源代码转换为目标平台的二进制文件。有点明显...但如果编译器以这种方式工作,那么同一个编译器如何用于不同的系统,如 x86、ARM、MIPS 等? 难道他们不应该“知道”硬
在我的 SDL 游戏中,出于游戏玩法和性能原因,我希望保留固定的游戏区域分辨率。 我想做的是有一个小分辨率(例如 320 * 240),并且在调整窗口大小时/切换到全屏模式时让 SDL/显卡缩放每个像
我正在使用这些方法来激活 SurFaceView 上的触摸焦点 private SurfaceView surfaceiew; private CameraSource camSource; priv
您好,当我从硬件菜单更改设备时,我遇到了这个奇怪的问题,但我想我可能遗漏了一些简单的东西。 我的 View Controller 中有这段代码: - (void)touchesBegan:(NSSet
编写一个名为 weird() 的函数,它将三个字符串作为参数并向后打印最长的一个。 (在平局的情况下,应该选择较早的参数字符串。 函数调用: weird("I", "Love", "Python")
您好,我正在尝试设置 hadoop 环境。简而言之,我要解决的问题涉及数十亿个大小为几 MB 的 XML 文件,使用 HIVE 从中提取相关信息,并对这些信息进行一些分析工作。我知道这在 hadoop
我知道 Phidgets,但是,我正在寻找可以与 C# 接口(interface)的一些其他类型的硬件。 谁有好东西? 最佳答案 查看 Netduino .它基于 Arduino,但使用 .Net
说一个函数(例如模乘法、正弦函数)是在硬件而不是软件中实现是什么意思? 最佳答案 在硬件中实现意味着电路(通过逻辑门等)可以执行操作。 例如,在 ALU 中,处理器在物理上能够将一个字节加到另一个字节
我需要编写一个程序,在可能状态的大空间中执行并行搜索,在此过程中发现了新区域(并开始了他们的探索),并且由于在其他地方获得的中间结果消除了可能性,因此提前终止了对某些区域的探索在其中发现新的有用结果。
我们需要通过带有硬件 token 的 EV 代码对 InstallShield 2013 Express 的安装进行签名,但是无法导出私钥证书文件,因此唯一的方法是使用 DigiCertUtil 工具
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 2 年前。 Improve this ques
我考虑从库中丢弃处理大端情况的代码,如果平台不是小端,则在初始化期间简单地抛出一个异常。如果我们限制为,我无法想象会有任何大端硬件 托管任何网站的典型服务器硬件 服务器根据开放计算项目规范 所有常见的
我知道这可以做到,但找不到交换目标调试设备的地方。我现在正在使用模拟器,但想切换到设备,反之亦然。谁能指出我正确的方向? 谢谢。 最佳答案 像这样.. 右键单击 PROJECT--->Run As--
我正在尝试创建一个监听音量键事件的服务。 每当按下音量键时,服务应向号码发送短信,但我无法检测到音量键事件。 最佳答案 您可以使用 OnKeyListener可以检测按键事件(包括音量键)。您可以找到
谁能解释一下中断如何从最低层(硬件)传递到应用程序。 所以在下图中我知道处理器之后发生了什么。 但是我想要从键盘按下到处理器的中断过程在硬件中发生了什么,例如它如何传递扫描代码,中断 Controll
我的任务是构建一个应用程序,其中业务用户将定义一些数据操作和处理规则(例如,取一个数值并将其平均分配给根据中指定的条件选择的多个记录)规则)。 每月必须运行一个批处理应用程序,以便根据定义的规则处理大
所以这是我的愚蠢问题: PGP/GPGP可以用来对文本进行签名,其他的使用公钥来验证。 比方说,非对称密码算法处理空间。 有没有什么算法可以处理时间? 例如在 2011-10-10 10:10:10
使用 nvcc 编译 CUDA 程序是否需要安装支持 CUDA 的显卡(在 Linux 中)?或者可以在任何地方编译程序并且只能在这样的系统上运行? 最佳答案 不,编译不需要显卡。 您甚至不需要一个来
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎不是关于 a specific programming problem, a softwar
我有一个奇怪的问题,但我对这个话题很感兴趣。 是否有可能直接访问当前基于 x64 的计算机的硬件,而无需使用某种 HAL(硬件抽象层)或其他操作系统(udev、upower 等)的附属物?我不是在谈论
我是一名优秀的程序员,十分优秀!