如何手动将 IronPython ctypes c_char_p 指针设置为绝对地址?
How do I set an IronPython ctypes c_char_p pointer to an absolute address manually?
我需要将字符指针指向的地址设置为绝对值。
在许多 Python 实现中(CPython 2.x、CPython 3.x、PyPy & ActivePython、...)这可以做到使用:
>>> c_char_p(0xcafebabe)
c_char_p(3405691582)
>>>
铁Python:
>>> c_char_p(0xcafebabe)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: expected char pointer, got long
>>>
IronPython 不会尝试设置指针的地址,而是将参数视为内容然后 returns 类型冲突。但是,上述其他 Python 发行版的功能不适用于 IronPython.
如何在 IronPython 中将 c_char_p
设置为绝对地址?
我的问题背景:
我开发了一个用Delphi编写的DLL。
DLL 的目的是为 Delphi 应用程序提供一个外部接口。
我可以通过 C 和 C++ 中的 DLL 成功控制应用程序。
客户要求更方便的解决方案 -> 他们想用 Python 控制应用程序。
我开发了一个 Python 包,实际上更容易使用。
所有 DLL 函数都必须使用指向表示设备的相同类型结构的指针来调用。
第一个调用的函数是 DLL 的 Init 函数,它使用默认值初始化结构。
不幸的是结构的设计缺少一个重要的项目,那就是RS232参数的配置,
因为在 DLL 的第一个版本中没有计划支持 RS232 设备。
为了仍然提供 RS232 支持,DLL 已被修改为使用设备结构中现有 char* 的绝对地址作为信号。
如果此 char* 的绝对地址为 0xCAFEBABE,则 DLL 会解析已放入该结构的另一个 char* 中的配置字符串。
这个丑陋的解决方案非常有效,并且不必更改结构的属性。
使用 CPython 2.x、CPython 3.x、PyPy 和 ActivePython 控制 DLL/application 时一切正常。
不幸的是,IronPython 在尝试将指针设置为绝对地址时报告错误。
显然,IPython对地址的限制更大,必须手动转换。这可以通过 [Python 2]: ctypes.cast(obj, type).
完成
code.py:
#!/usr/bin/env python2
import sys
import ctypes
CharPtr = ctypes.POINTER(ctypes.c_char)
def main():
pchar0 = ctypes.cast(ctypes.c_char_p("Dummy text"), CharPtr) # Create an object that will yield a valid memory address
buf_addr = ctypes.addressof(pchar0.contents) # Raw buffer address
print("Raw buffer address: 0x{:016X}".format(buf_addr))
cp0 = ctypes.cast(buf_addr, ctypes.c_char_p)
print("cp0 ({:s}) value: {:s}\n".format(cp0.__class__.__name__, cp0.value))
cp1 = ctypes.c_char_p(buf_addr)
print("cp1 ({:s}) value: {:s}".format(cp1.__class__.__name__, cp1.value))
if __name__ == "__main__":
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
main()
输出:
[cfati@CFATI-5510-0:e:\Work\Dev\Whosebug\q055118583]> "e:\Work\Dev\VEnvs\py_064_02.07.15_test0\Scripts\python.exe" code.py
Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32
Raw buffer address: 0x00000000036D0690
cp0 (c_char_p) value: Dummy text
cp1 (c_char_p) value: Dummy text
[cfati@CFATI-5510-0:e:\Work\Dev\Whosebug\q055118583]> "c:\Install\IronLanguages\IronPython.07.09\net45\ipy.exe" code.py
Python 2.7.9 (IronPython 2.7.9 (2.7.9.0) on .NET 4.0.30319.42000 (64-bit)) on cli
Raw buffer address: 0x00000209BFF2E860
cp0 (c_char_p) value: Dummy text
Traceback (most recent call last):
File "code.py", line 24, in <module>
File "code.py", line 18, in main
TypeError: expected char pointer, got long
备注:
- pchar0的目的只是得到一个有效的内存地址(buf_addr) 指向
char*
(因为 0xCafeBabe 在我的 Python 过程中没有意义)
- cp1 (以相反的顺序获取它们)是问题陈述:试图从内存地址创建
ctypes.c_char_p
(根据最新的问题编辑:那个由.dll中的某些例程填充char*
(必须在当前进程中加载))
- 这在 CPython 中有效(根据问题),但在 中引发了 TypeError ]IPython
- cp0 是问题的解决方案:尝试从 相同的 内存地址创建一个
ctypes.c_char_p
- 适用于 CPython 和 IPython
我需要将字符指针指向的地址设置为绝对值。
在许多 Python 实现中(CPython 2.x、CPython 3.x、PyPy & ActivePython、...)这可以做到使用:
>>> c_char_p(0xcafebabe)
c_char_p(3405691582)
>>>
铁Python:
>>> c_char_p(0xcafebabe)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: expected char pointer, got long
>>>
IronPython 不会尝试设置指针的地址,而是将参数视为内容然后 returns 类型冲突。但是,上述其他 Python 发行版的功能不适用于 IronPython.
如何在 IronPython 中将 c_char_p
设置为绝对地址?
我的问题背景:
我开发了一个用Delphi编写的DLL。 DLL 的目的是为 Delphi 应用程序提供一个外部接口。 我可以通过 C 和 C++ 中的 DLL 成功控制应用程序。 客户要求更方便的解决方案 -> 他们想用 Python 控制应用程序。 我开发了一个 Python 包,实际上更容易使用。 所有 DLL 函数都必须使用指向表示设备的相同类型结构的指针来调用。 第一个调用的函数是 DLL 的 Init 函数,它使用默认值初始化结构。 不幸的是结构的设计缺少一个重要的项目,那就是RS232参数的配置, 因为在 DLL 的第一个版本中没有计划支持 RS232 设备。 为了仍然提供 RS232 支持,DLL 已被修改为使用设备结构中现有 char* 的绝对地址作为信号。 如果此 char* 的绝对地址为 0xCAFEBABE,则 DLL 会解析已放入该结构的另一个 char* 中的配置字符串。 这个丑陋的解决方案非常有效,并且不必更改结构的属性。 使用 CPython 2.x、CPython 3.x、PyPy 和 ActivePython 控制 DLL/application 时一切正常。 不幸的是,IronPython 在尝试将指针设置为绝对地址时报告错误。
显然,IPython对地址的限制更大,必须手动转换。这可以通过 [Python 2]: ctypes.cast(obj, type).
完成code.py:
#!/usr/bin/env python2
import sys
import ctypes
CharPtr = ctypes.POINTER(ctypes.c_char)
def main():
pchar0 = ctypes.cast(ctypes.c_char_p("Dummy text"), CharPtr) # Create an object that will yield a valid memory address
buf_addr = ctypes.addressof(pchar0.contents) # Raw buffer address
print("Raw buffer address: 0x{:016X}".format(buf_addr))
cp0 = ctypes.cast(buf_addr, ctypes.c_char_p)
print("cp0 ({:s}) value: {:s}\n".format(cp0.__class__.__name__, cp0.value))
cp1 = ctypes.c_char_p(buf_addr)
print("cp1 ({:s}) value: {:s}".format(cp1.__class__.__name__, cp1.value))
if __name__ == "__main__":
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
main()
输出:
[cfati@CFATI-5510-0:e:\Work\Dev\Whosebug\q055118583]> "e:\Work\Dev\VEnvs\py_064_02.07.15_test0\Scripts\python.exe" code.py Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32 Raw buffer address: 0x00000000036D0690 cp0 (c_char_p) value: Dummy text cp1 (c_char_p) value: Dummy text [cfati@CFATI-5510-0:e:\Work\Dev\Whosebug\q055118583]> "c:\Install\IronLanguages\IronPython.07.09\net45\ipy.exe" code.py Python 2.7.9 (IronPython 2.7.9 (2.7.9.0) on .NET 4.0.30319.42000 (64-bit)) on cli Raw buffer address: 0x00000209BFF2E860 cp0 (c_char_p) value: Dummy text Traceback (most recent call last): File "code.py", line 24, in <module> File "code.py", line 18, in main TypeError: expected char pointer, got long
备注:
- pchar0的目的只是得到一个有效的内存地址(buf_addr) 指向
char*
(因为 0xCafeBabe 在我的 Python 过程中没有意义) - cp1 (以相反的顺序获取它们)是问题陈述:试图从内存地址创建
ctypes.c_char_p
(根据最新的问题编辑:那个由.dll中的某些例程填充char*
(必须在当前进程中加载))- 这在 CPython 中有效(根据问题),但在 中引发了 TypeError ]IPython
- cp0 是问题的解决方案:尝试从 相同的 内存地址创建一个
ctypes.c_char_p
- 适用于 CPython 和 IPython