How do I set an IronPython ctypes c_char_p pointer to an absolute address manually?

感情迁移 提交于 2019-12-11 15:39:35

问题


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

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)
>>>

in IronPython:

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

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.

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

The background for my question:

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.


回答1:


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()

Output:

[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

Notes:

  • 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
  • cp0 is the problem solution: trying to create a ctypes.c_char_p from the same memory address
    • That works in CPython and IPython


来源:https://stackoverflow.com/questions/55118583/how-do-i-set-an-ironpython-ctypes-c-char-p-pointer-to-an-absolute-address-manual

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!