Open strongly-typed opened 2 years ago
The "simpel_example" from the project already give different results when using msvcrt.dll
. So it is not a problem of my DLL.
The code uses pointers and memset
# Add 4 'O' to the string starting from position 6
p = ctypes.cast(ctypes.addressof(mut_str) + 5, ctypes.POINTER(ctypes.c_char))
libc.memset(p, ctypes.c_char(b"O"), 4)
# Print the modified string
libc.puts(mut_str)
The expected result (which is produced by CPython) is XXXXXOOOO
. IronPython does not write to the correct memory.
PS C:\Users\Sascha\Desktop\working_directory\Python-using-C-CPP-libraries-with-ctypes\simple_example> $Env:IRONPYTHONPATH="C:\Users\Sascha\Desktop\working_directory\ironpython3\Src\StdLib\Lib"
PS C:\Users\Sascha\Desktop\working_directory\Python-using-C-CPP-libraries-with-ctypes\simple_example> ..\..\ironpython3\bin\Release\net6.0\ipy.exe .\t0.py
Succesfully loaded the system C library from "C:\Windows\system32\msvcrt.dll"
Hello from Python to C
Using the C printf function from Python ...
XXXXX
XXXXX
PS C:\Users\Sascha\Desktop\working_directory\Python-using-C-CPP-libraries-with-ctypes\simple_example> python .\t0.py
Succesfully loaded the system C library from "C:\Windows\system32\msvcrt.dll"
Hello from Python to C
Using the C printf function from Python ...
XXXXX
XXXXXOOOO
The problem also exists on macOS
➜ simple_example git:(master) ~/Dev/ironpython3/bin/Debug/net6.0/ipy t0.py
Succesfully loaded the system C library from "/usr/lib/libc.dylib"
Hello from Python to C
Using the C printf function from Python ...
XXXXX
XXXXX
➜ simple_example git:(master) python3.10 t0.py
Succesfully loaded the system C library from "/usr/lib/libc.dylib"
Hello from Python to C
Using the C printf function from Python ...
XXXXX
XXXXXOOOO
➜ simple_example git:(master) sw_vers
ProductName: Mac OS X
ProductVersion: 10.15.7
BuildVersion: 19H2026
I can see the following difference between
IronPython
>>> mut_str.__class__
<class 'unknown.c_char_Array_10'>
and CPython
>>> mut_str.__class__
<class 'ctypes.c_char_Array_10'>
At least this code does something expected (on macOS):
import ctypes, ctypes.util
path_libc = ctypes.util.find_library("c")
libc = ctypes.CDLL(path_libc)
x = ctypes.create_string_buffer(10)
z = libc.memset(x, ctypes.c_char(b'X'), 5)
p = ctypes.addressof(x) + 5
# p = ctypes.cast(p, ctypes.POINTER(ctypes.c_char)) # This does break it
libc.memset.argtypes = [ctypes.c_void_p, ctypes.c_char, ctypes.c_long] # This is necessary
z = libc.memset(p, ctypes.c_char(b'O'), 4)
libc.puts(x)
XXXXXOOOO
10
Also works on Windows:
XXXXXOOOO
0
No idea if it's related, but the simple example issue reminds me of the following (from https://github.com/IronLanguages/ironpython2/issues/653)
import ctypes
class POINT(ctypes.Structure):
_fields_ = [('x', ctypes.c_long), ('y', ctypes.c_long)]
buf = ctypes.create_string_buffer(ctypes.sizeof(POINT))
ptr = ctypes.cast(buf, ctypes.POINTER(POINT))
ctypes.windll.user32.GetCursorPos(ptr)
print(ptr.contents.x, ptr.contents.y)
If I tweak it to not pass the pointer to the function then it seems to work:
import ctypes
class POINT(ctypes.Structure):
_fields_ = [('x', ctypes.c_long), ('y', ctypes.c_long)]
buf = ctypes.create_string_buffer(ctypes.sizeof(POINT))
ptr = ctypes.cast(buf, ctypes.POINTER(POINT))
ctypes.windll.user32.GetCursorPos.argtypes = [ctypes.c_void_p]
ctypes.windll.user32.GetCursorPos(ctypes.addressof(buf))
print(ptr.contents.x, ptr.contents.y)
I have a vague recollection that the issue might have been that it was passing the address of the pointer instead of the value of the pointer to the function - but it was a few years ago that I looked at it so I could be wrong. Unfortunately I never came up with a solution.
I tried to use
ctypes
to interface to some C/C++ code as DLL with IronPython on Windows. I got random segfaults and errors in malloc. I am trying to boil it down and moved to a simple project that works with CPython but fails with IronPython2.7 and IronPython3.4-beta.The project to test with is Python-using-C-CPP-libraries-with-ctypes. Great shout-out to @sol-prog
I am using Windows 10 21H1 OS build 19044.1865 and Visual Studio Community 2022. Detailed environment information at the bottom.
I used the released IronPython versions and also built IronPython3.4 from source (so trying that the same compiler is used for the DLL and IronPython binaries).
When I compile the DLL using MSVC (cbmp.dll) and run it with IronPython3.4 the code does not run due to some internal memory corruption.
When running with Python3 the code works just fine and produces valid output.
In
cbmp.py
I had to modify the loading of the library to:I compiled the DLL in the following way (from the "x64 Native Tools Command Prompt for VS 2022")
x86 (32-bit) Test
I also build IronPython x86 and the DLL with x86 to test:
From "x86 Native Tools Command Prompt for VS 2022":
Build Python for x86. Only the net46 version seemed to be build:
This gives some access violation. The code works with CPython and the DLL seems to be fine. I guess something in
ctypes
is broken in IronPython?!Or what are the best/correct compiler parameters I should use to compile the DLL with? To match calling conventions, pointer sizes, et cetera?
Environment
"x64 Native Tools Command Prompt for VS 2022"