如何手动将IronPython ctypes c_char_p指针设置为绝对地址? [英] How do I set an IronPython ctypes c_char_p pointer to an absolute address manually?

查看:160
本文介绍了如何手动将IronPython ctypes c_char_p指针设置为绝对地址?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将字符指针指向的地址设置为绝对值.

I need to set the address to which a character pointer points to as an absolute value.

在许多Python实现中(CPyhton 2.x,CPython 3.x,PyPy和ActivePython等),可以使用以下方法完成:

In many Python implementations (CPyhton 2.x, CPython 3.x, PyPy & ActivePython, ...) this can be done using:

>>> c_char_p(0xcafebabe)
c_char_p(3405691582)
>>>

在IronPython中:

in IronPython:

>>> c_char_p(0xcafebabe)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: expected char pointer, got long
>>>

IronPython不会尝试设置指针的地址,而是将参数视为内容,然后返回类型冲突.但是,上述其他Python发行版的功能不适用于IronPython.

IronPython does not attempt to set the address of the pointer, but treats the argument as content and then returns a type conflict. However, the functionality of the other Python distributions mentioned above does not apply to IronPython.

如何在IronPython中将c_char_p设置为绝对地址?

What can I do to set a c_char_p to an absolute address in IronPython?

我的问题的背景:

我已经开发了一个用Delphi编写的DLL. DLL的目的是为Delphi应用程序提供外部接口. 我可以通过C和C ++中的DLL成功控制应用程序. 客户要求提供更方便的解决方案->他们希望使用Python控制应用程序. 我已经开发了一个实际上更易于使用的Python软件包. 必须使用指向表示设备的相同结构类型的指针来调用所有DLL函数. 调用的第一个函数是DLL的Init函数,该函数使用默认值初始化结构. 不幸的是,结构的设计缺少一个重要的项目,那就是RS232参数的配置, 因为在DLL的第一个版本中没有计划对RS232设备的支持. 为了仍然提供RS232支持,已对DLL进行了修改,以使用设备结构中现有char *的绝对地址作为信号. 如果此char *的绝对地址为0xCAFEBABE,则DLL解析已放入该结构的另一个char *中的配置字符串. 这种丑陋的解决方案效果很好,并且不必更改结构的属性. 使用CPyhton 2.x,CPython 3.x,PyPy& ActivePython. 不幸的是,IronPython在尝试将指针设置为绝对地址时报告错误.

I have developed a DLL which is written in Delphi. The purpose of the DLL is to have an external interface to a Delphi application. I can control the application via the DLL in C and C++ successfully. Customers requested for a more convenient solution -> they want to control the application with Python. I've developed a Python package that's actually much easier to use. All DLL functions have to be called with a pointer to the same type of structure which represents a device. The first function to call is the DLL's Init function which initialises the structure with default values. Unfortunately the design of the structure lacks an important item, that is the configuration of RS232 parameters, because support for RS232 devices was not planned in the first version of the DLL. To still provide RS232 support, the DLL has been modified to use the absolute address of an existing char* in the device structure as a signal. If this char* has the absolute address 0xCAFEBABE, the DLL parses a configuration string that has been put into another char* of the structure. This ugly solution works very well and the attributes of the structure did not have to be changed. Everything works fine when controlling the DLL/application with CPyhton 2.x, CPython 3.x, PyPy & ActivePython. Unfortunately IronPython reports an error when trying to set the pointer to the absolute address.

推荐答案

显然, IPython 对于地址的限制更大,必须手动执行转换.这可以通过 [Python 2]:ctypes完成. cast ( obj,键入).

Apparently, IPython is more restrictive when it comes to addresses, and conversions must be performed manually. This can done via [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\StackOverflow\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\StackOverflow\q055118583]> "c:\Install\IronLanguages\IronPython\02.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 的目的只是获得指向char*有效内存地址( buf_addr )(如 0xCafeBabe 在我的 Python 过程中没有任何意义)
  • 问题
  • cp1 (以相反的顺序获取)是问题的陈述:尝试从内存地址创建ctypes.c_char_p(根据最新的问题用char*填充)通过 .dll 中的一些例程(必须在当前进程中加载​​)
    • (根据问题)在 CPython 中有效,但在 IPython
    • 中引发 TypeError
    • pchar0's purpose is just to get a valid memory address (buf_addr) which points to a char* (as 0xCafeBabe has no meaning in my Python process)
    • cp1 (take them in reversed order) is the problem statement: trying to create a ctypes.c_char_p from a memory address (according to the latest question edit: that is filled with a char* by some routines in a .dll (which must be loaded in the current process))
      • That works (according to the question) in CPython, but raises the TypeError in IPython
      • CPython IPython
      • 中有效
      • That works in CPython and IPython

      这篇关于如何手动将IronPython ctypes c_char_p指针设置为绝对地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆