Skip to content

is there any way to convert NumSharp.NDArray to Numpy.NDarray? #383

Closed

Description

@lelelemonade
No description provided.

Activity

  1. Nucs commented on Jan 6, 2020

    @Nucs
    Member

    Me and @henon have collaborated just two days ago on a solution for that,
    The trick is to create a python scope, load a script that takes in a pointer-length and returns an np.ndarray
    Remember! you have to keep reference to the original NDArray, otherwise the NDArray will be disposed and will release the memory. (@henon is there a tag field we can use in NDarray?)

    Note: the code below is psuedo, the rest of the code can be found here: ConsoleApp9.zip

    numpy_interop.py as embedded resource

    import numpy as np
    import ctypes
    
    def to_numpy(ptr, bytes, dtype, shape):
        return np.frombuffer((ctypes.c_uint8*(bytes)).from_address(ptr), dtype).reshape(shape)

    PythonExtensions.cs

    public static class PythonExtensions {
    
        ...
        private static PyScope NumpyInteropScope;
        private static PyObject NumpyConverter;
    
        public static unsafe NDarray ToNumpyNET(this NDArray nd) {
            using (Py.GIL()) {
                if (NumpyInteropScope == null) {
                    NumpyInteropScope = Py.CreateScope();
                    NumpyInteropScope.ExecResource("numpy_interop.py");
                    NumpyConverter = NumpyInteropScope.GetFunction("to_numpy");
                }
    
                return new NDarray(NumpyConverter.Invoke(new PyLong((long) nd.Unsafe.Address),
                    new PyLong(nd.size * nd.dtypesize),
                    new PyString(nd.dtype.Name.ToLowerInvariant()),
                    new PyTuple(nd.shape.Select(dim => (PyObject) new PyLong(dim)).ToArray())));
            }
        }
    }

    main.cs

    using numsharp_np = NumSharp.np;
    using numpy_np = Numpy.np;
    static void Main(string[] args) {
        var numsharp_nd = numsharp_np.arange(10);
        var numpy_nd = numsharp_nd.ToNumpyNET();
        numpy_nd[1] = (NDarray) 5;
        Debug.Assert(numsharp_nd[1].array_equal(5));
        Console.WriteLine("numsharp_nd[1].array_equal(5) is indeed true!");
    }
  2. Nucs commented on Jan 6, 2020

    @Nucs
    Member

    Added some changes that will make sure the NDarray will hold reference to the NDArray as long as the PyObject doesnt change internally.

    ConsoleApp9.zip

  3. henon commented on Jan 6, 2020

    @henon
    Contributor

    Remember! you have to keep reference to the original NDArray, otherwise the NDArray will be disposed and will release the memory. (@henon is there a tag field we can use in NDarray?)

    Not yet, but I will add one in Numpy.NET and support this.

  4. davidvct commented on Feb 24, 2023

    @davidvct

    Hi, could you provide instruction on how to use the ConsoleApp9.zip? And does it able to convert Numpy array back to NumSharp array?

  5. henon commented on Feb 24, 2023

    @henon
    Contributor

    @davidvct, if I remember correctly I have added support for copying data to and from Numpy.NET like @Nucs did in this solution. Read this to see how: https://github.com/SciSharp/Numpy.NET#create-a-numpy-array-from-a-c-array-and-vice-versa

  6. Nucs commented on Sep 7, 2026

    @Nucs
    Member

    @lelelemonade @davidvct, the manual pointer-scope trick from this thread is superseded. The new NumSharp.Interop.pythonnet package (0.70.0, #628) crosses both ways zero-copy, with GC-safe leases (no more "keep a reference or it gets disposed").

    Set up the Python engine once at startup - either point pythonnet at an installed Python, or deploy one from NuGet with Python.Included (no system install needed):

    using NumSharp;
    using NumSharp.Interop.PythonNet;
    using Python.Runtime;
    
    // Option A - existing Python: the PYTHONNET_PYDLL env var, or the DLL directly
    Runtime.PythonDLL = "python312.dll";   // or Environment.GetEnvironmentVariable("PYTHONNET_PYDLL")
    PythonEngine.Initialize();
    
    // Option B - deploy an embedded Python from NuGet (dotnet add package Python.Included)
    await Python.Included.Installer.SetupPython();
    await Python.Included.Installer.PipInstallModule("numpy");
    PythonEngine.Initialize();

    Explicit:

    var nd = np.arange(6).reshape(2, 3);
    
    using (Py.GIL())
    {
        // zero-copy: numpy shares NumSharp's buffer
        dynamic npArr = nd.ToNumpy();
        Console.WriteLine(npArr.sum());   // 15
    }

    Implicit (register the codec once, then NumSharp arrays auto-convert):

    NDArrayPythonInterop.RegisterCodec();   // once per process
    
    var nd = np.arange(6).reshape(2, 3);
    using (Py.GIL())
    {
        dynamic numpy = Py.Import("numpy");
        Console.WriteLine(numpy.sum(nd));   // 15   (nd auto-encoded by the codec)
    }

    Requires NumSharp.Interop.pythonnet (dotnet add package NumSharp.Interop.pythonnet). Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions