Describe what you were trying to get done.
Array.CreateInstance for multi-dimensional arrays worked fine in v2.4.0. After upgrading to v2.5.0+, an error message gets thrown.
What commands did you run to trigger this issue?
import numpy as np
import ctypes
import clr, System
from System import Array, Int32
from System.Runtime.InteropServices import GCHandle, GCHandleType
import sys
import os
_MAP_NP_NET = {
np.dtype('float32'): System.Single,
np.dtype('float64'): System.Double,
np.dtype('int8') : System.SByte,
np.dtype('int16') : System.Int16,
np.dtype('int32') : System.Int32,
np.dtype('int64') : System.Int64,
np.dtype('uint8') : System.Byte,
np.dtype('uint16') : System.UInt16,
np.dtype('uint32') : System.UInt32,
np.dtype('uint64') : System.UInt64,
np.dtype('bool') : System.Boolean,
}
def asNetArray(npArray):
dims = npArray.shape
dtype = npArray.dtype
netDims = Array.CreateInstance(Int32, npArray.ndim)
for I in range(npArray.ndim):
netDims[I] = int(dims[I])
if not npArray.flags.c_contiguous:
npArray = npArray.copy(order='C')
assert npArray.flags.c_contiguous
try:
netArray = Array.CreateInstance(_MAP_NP_NET[dtype], netDims)
except KeyError:
raise NotImplementedError("asNetArray does not yet support dtype {}".format(dtype))
try: # Memmove
destHandle = GCHandle.Alloc(netArray, GCHandleType.Pinned)
sourcePtr = npArray.__array_interface__['data'][0]
destPtr = destHandle.AddrOfPinnedObject().ToInt64()
ctypes.memmove(destPtr, sourcePtr, npArray.nbytes)
finally:
if destHandle.IsAllocated: destHandle.Free()
return netArray
if __name__ == '__main__':
foo = np.full([1024,1024], 2.5, dtype=np.int32)
netFoo = asNetArray( foo )
Traceback (most recent call last):
File "pythonnetUtils.py", line 53, in <module>
netFoo = asNetArray( foo )
File "pythonnetUtils.py", line 37, in asNetArray
netArray = Array.CreateInstance(_MAP_NP_NET[dtype], netDims)
TypeError: No method matches given arguments for CreateInstance: (<class 'CLR.CLR Metatype'>, <class 'System.Int32[]'>)
Hm, @pkthong can you double check your code? When I do str(Int32) in the latest build, I get <class 'System.Int32'>, not <class 'CLR.CLR Metatype'>.
Python 3.8.0 (default, Nov 6 2019, 16:00:02) [MSC v.1916 64 bit (AMD64)] :: Anaconda, Inc. on win32
Type "help", "copyright", "credits" or "license" for more information.
import clr, System
print(type(System.Int32))
print(str(System.Int32))
print(clr.__version__)
3.0.0dev
This at commit-ish (7a9dcfa )
Hmm, I'll give that a try locally. The "type" it lists there is correct for Python, CLR.CLR Metatype (awful name...) is the Python type for System.Type objects, but it seems like the method binding doesn't make that link anymore.
Running through the changes between v2.4.0 and v2.5.0, the last commit that works for the above test is (4a92d80)
Okay, then it's indeed https://github.com/pythonnet/pythonnet/pull/1106. That change actually improved things, in that it allows "proper" use of params arrays (like CreateInstance uses). You can fix your code by changing
netArray = Array.CreateInstance(_MAP_NP_NET[dtype], netDims)
to
netArray = Array.CreateInstance(_MAP_NP_NET[dtype], *netDims)
I'm not yet completely sure whether we want to fix it (we definitely want to keep the feature, maybe we can still allow the direct passing of the array as a fallback), but I acknowledge breakage :)
/edit: Actually you can even drop the whole copy-to-.net part and replace it by
netArray = Array.CreateInstance(_MAP_NP_NET[dtype], *npArray.shape)
The above suggestion seems to execute, yet accessing the array results in a System.AccessViolationException.
To reproduce this, add the following to the test code.
netFoo2 = Array.Copy(netFoo)
Most helpful comment
Running through the changes between v2.4.0 and v2.5.0, the last commit that works for the above test is (4a92d80)