[Python.NET] Efficient copy of .NET Array to ctypes or numpy array.
jeff at coderforlife.com
Fri May 23 18:27:25 CEST 2014
The problem with your current code is that as soon as you call
src_hndl.Free() the pointer is not necessarily valid any more! .NET is
allowed to move the memory contents of objects at will unless they are
pinned (which is what the first line does). By freeing the GCHandle it is
no longer pinned and liable to move/freed as the garbage collector compacts
memory. Also, in 64-bit Python, you will need to call ToInt64() instead of
ToInt32(). In fact, it may always be reasonable to call ToInt64() since
Python's integer type will likely deal with it being 32 or 64-bit
So all in all:
- Use ToInt64() instead of ToInt32(), at least in 64-bit Python (e.g.
x.ToInt64() if ctypes.sizeof(ctypes.c_void_p) == 8 else x.ToInt32())
- Do not call GCHandle.Free() until you are completely done with the
memory pointer, but make sure you definitely call it after you are done
with the memory pointer because otherwise the garbage collector can never
free or move the memory that is pinned (resulting in memory leaks or
On Fri, May 23, 2014 at 3:34 AM, Dave Cook <daverz at gmail.com> wrote:
> (Sorry for screwing up the thread; I messed up my list subscription.
> This is a response to
> https://mail.python.org/pipermail/pythondotnet/2014-May/001525.html )
> Thanks, Jeffrey, that's awesome. Since the pointer can be directly
> accessed, np.frombuffer() can be used to avoid a copy.
> src_hndl = GCHandle.Alloc(src, GCHandleType.Pinned)
> src_ptr = src_hndl.AddrOfPinnedObject().ToInt32()
> bufType = ctypes.c_double*len(src)
> cbuf = bufType.from_address(src_ptr)
> dest = np.frombuffer(cbuf, dtype=cbuf._type_)
> if src_hndl.IsAllocated: src_hndl.Free()
> Dave Cook
> Python.NET mailing list - PythonDotNet at python.org
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the PythonDotNet