I need to pass a System.IntPtr to a .NET function (Python with pythonnet). This pointer should refer to a struct created in cffi.
I found this:
from CLR.System import IntPtr, Int32
i = Int32(32)
p = IntPtr.op_Explicit(i)
This is what I tried so far
import clr
from cffi import FFI
ffi = FFI()
custom_t = '''
typedef struct
{
float x;
float y;
float z;
} float3;
'''
ffi.cdef(custom_t)
cfloat3 = ffi.new("float3 *")
cfloat3.x = 1.0
cfloat3.y = 2.0
cfloat3.z = 3.0
print(cfloat3)
from System import IntPtr
p = IntPtr.op_Explicit(id(cfloat3)) #works, sort of...
print(p)
#I would rather see something like
p2 = IntPtr.op_Explicit(ffi.addressof(cfloat3).value)
p3 = IntPtr(ffi.cast("float3*", cfloat3))
p4 = IntPtr(ffi.cast("void3*", cfloat3))
#type(_), ffi.typeof(_), ffi.typeof(_).kind, ffi.addressof()
But I am not sure if using IntPtr.op_Explicit is the best solution. It looks a bit like workaround in combination with id()
and I am pretty sure there is a better solution.
There is no direct support for CFFI inside Python.Net or vice-versa, so you need to cast the pointer from one library to an integer and reimport that integer into the other library.
From CFFI,
intaddr = ffi.cast("intptr_t", p)
will give you an integer. Then you can probably doIntPtr(intaddr)
.FFI has an addressof function built in:
http://cffi.readthedocs.io/en/latest/ref.html#ffi-addressof
The solution to this is to use the
Overloads
method ofIntPtr
as mentioned here and here.
Here is a working example:
Some further info on what is happening above (found here and there):