问题
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 achar*
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