using RGiesecke.DllExport;
 
using System;
 
using System.Text;
 
using System.Runtime.InteropServices;
 
 
 
using AitMduManager;
 
 
 
/*
 
#region Assembly AitMduManager, Version=1.2.0.0, Culture=neutral, PublicKeyToken=null
 
// AitMduManager.dll
 
#endregion
 
*/
 
 
 
// https://blogs.msdn.microsoft.com/jaredpar/2008/11/05/dereference-a-double-intptr/    
 
 
 
 
 
namespace NativeExports
 
{
 
    class Program
 
    {
 
 
 
        static MduManager SD4 
= new MduManager
();  
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static int SD4_BlockError()
 
        {
 
            return SD4.BlockError;
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static void SD4_SetBlockTimeout(uint a)
 
        {
 
            SD4.BlockTimeout = a;
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static uint SD4_GetBlockTimeout()
 
        {
 
            return SD4.BlockTimeout;
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static long SD4_BlockTransferTime()
 
        {
 
            return SD4.BlockTransferTime;
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static uint SD4_GetDriverTimeout()
 
        {
 
            return SD4.DriverTimeout;
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static void SD4_SetDriverTimeout(uint tout)
 
        {
 
            SD4.DriverTimeout = tout;
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static IntPtr SD4_Version()
 
        {
 
            return Marshal.StringToHGlobalAnsi(SD4.Version);
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static int SD4_WordsTransferred()
 
        {
 
            return SD4.WordsTransferred;
 
        }
 
 
 
        /*
 
 
 
        public event EventHandler DeviceAttached;
 
        public event EventHandler DeviceRemoved;
 
        public event EventHandler FirmwareStatusChanged;
 
        */
 
 
 
        static IntPtr SD4_ArrayToIntPtr(int[] retval)
 
        {
 
            SD4_AllocateMemory(len);
 
            Marshal.Copy(retval, 0, _unmanagedMemory, retval.Length);
 
            return _unmanagedMemory;
 
        }
 
 
 
        static IntPtr SD4_ArrayToIntPtr(ushort[] retval)
 
        {
 
            SD4_AllocateMemory(len);
 
            Marshal.Copy((short[])(object) retval, 0, _unmanagedMemory, retval.Length);
 
            return _unmanagedMemory;
 
        }
 
 
 
        static IntPtr SD4_ArrayToIntPtr(uint[] retval)
 
        {
 
            SD4_AllocateMemory(len);
 
            Marshal.Copy((int[])(object) retval, 0, _unmanagedMemory, retval.Length);
 
            return _unmanagedMemory;
 
        }
 
 
 
        static IntPtr SD4_ArrayToIntPtr(byte[] retval)
 
        {
 
            SD4_AllocateMemory(len);
 
            Marshal.Copy(retval, 0, _unmanagedMemory, retval.Length);
 
            return _unmanagedMemory;
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static IntPtr SD4_FindDevices( ref int len)
 
        {
 
            uint[] devices = SD4.FindDevices();
 
            if (devices == null)
 
            {
 
                len = 0;
 
                return IntPtr.Zero;
 
            }
 
            else
 
            {
 
                len = devices.Length;
 
                return SD4_ArrayToIntPtr(devices);
 
            }
 
 
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static int SD4_GetDeviceCount()
 
        {
 
            return SD4.GetDeviceCount();
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static IntPtr SD4_GetDeviceList( ref int len)
 
        {
 
            uint[] devices = SD4.GetDeviceList();
 
            if (devices == null)
 
            {
 
                len = 0;
 
                return IntPtr.Zero;
 
            }
 
            else
 
            {
 
                len = devices.Length;
 
                return SD4_ArrayToIntPtr(devices);
 
            }
 
        }
 
 
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static IntPtr SD4_GetUsbFirmwareVersionByDevice(uint deviceId)
 
        {
 
            return Marshal.StringToHGlobalAnsi(SD4.GetUsbFirmwareVersion(deviceId));
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static IntPtr SD4_GetUsbFirmwareVersion(int index)
 
        {
 
            return Marshal.StringToHGlobalAnsi(SD4.GetUsbFirmwareVersion(index));
 
        }
 
 
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static bool SD4_IsDeviceAttached(uint deviceId)
 
        {
 
            return SD4.IsDeviceAttached(deviceId);
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static bool SD4_ProgramFpgaFirmwareByDevice(uint deviceId, IntPtr data, int len)
 
        {
 
            byte[] fpgaFirmware 
= new byte[len
];  
            Marshal.Copy(data, fpgaFirmware, 0, len);
 
            return SD4.ProgramFpgaFirmware(deviceId, fpgaFirmware);
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static bool SD4_ProgramFpgaFirmware(int index, IntPtr data, int len)
 
        {
 
            byte[] fpgaFirmware 
= new byte[len
];  
            Marshal.Copy(data, fpgaFirmware, 0, len);
 
            return SD4.ProgramFpgaFirmware(index, fpgaFirmware);
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static bool SD4_ProgramUsbFirmware(int index, IntPtr data, int len)
 
        {
 
            byte[] usbFirmware 
= new byte[len
];  
            Marshal.Copy(data, usbFirmware, 0, len);
 
            return SD4.ProgramUsbFirmware(index, usbFirmware);
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static ushort SD4_Read(uint deviceId, int address)
 
        {
 
            return SD4.Read(deviceId, address);
 
        }
 
 
 
        
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static IntPtr SD4_ReadByteArray(uint deviceId, int address, int requested_elements , ref int len)
 
        {
 
            SD4_AllocateByteBuffer(requested_elements);
 
            SD4.Read(deviceId, address, SD4_ByteBuffer);
 
            _unmanagedMemory = SD4_ArrayToIntPtr(SD4_ByteBuffer);
 
            len = _unmanagedMemoryLength;
 
            return _unmanagedMemory;
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static IntPtr SD4_ReadUShortArray(uint deviceId, int address, int requested_elements, ref int len)
 
        {
 
/*
 
            System.Console.WriteLine("SD4_ReadUShortArray");
 
            System.Console.WriteLine(deviceId);
 
            System.Console.WriteLine(address);
 
            System.Console.WriteLine(requested_elements);
 
*/
 
            
 
            SD4_AllocateUshortBuffer(requested_elements);
 
            SD4.Read(deviceId, address, SD4_UShortBuffer);
 
            _unmanagedMemory = SD4_ArrayToIntPtr(SD4_UShortBuffer);
 
            len = _unmanagedMemoryLength;
 
            return _unmanagedMemory;
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static void SD4_ReconfigureByDevice(uint deviceId)
 
        {
 
            SD4.Reconfigure(deviceId);
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static void SD4_Reconfigure(int index)
 
        {
 
            SD4.Reconfigure(index);
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static void SD4_ReconnectByDevice(uint deviceId)
 
        {
 
            SD4.Reconnect(deviceId);
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static void SD4_Reconnect(int index)
 
        {
 
            SD4.Reconnect(index);
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static void SD4_ResetFpga(int index)
 
        {
 
            SD4.ResetFpga(index);
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static void SD4_ResetFpgaByDevice(uint deviceId)
 
        {
 
            SD4.ResetFpga(deviceId);
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static void SD4_ResetUsb(int index)
 
        {
 
            SD4.ResetUsb(index);
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static void SD4_ResetUsbByDevice(uint deviceId)
 
        {
 
            SD4.ResetUsb(deviceId);
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static void SD4_Write(uint deviceId, int address, ushort data)
 
        {
 
            SD4.Write(deviceId, address, data);
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static int SD4_WriteArray(uint deviceId, int address, IntPtr data, int len)
 
        {          
 
            ushort[] udata 
= new ushort[len
];  
            Marshal.Copy( data, (int[])(object) udata,0, len);
 
            return SD4.Write(deviceId, address, udata);
 
        }
 
        /*
 
        public sealed class DeviceChangedEventArgs : EventArgs
 
        {
 
            public DeviceChangedEventArgs();
 
 
 
            public uint DeviceId { get; set; }
 
            public int DeviceIndex { get; set; }
 
        }
 
        public sealed class FirmwareStatusEventArgs : EventArgs
 
        {
 
            public FirmwareStatusEventArgs();
 
 
 
            public uint DeviceId { get; set; }
 
            public int DeviceIndex { get; set; }
 
            public string FirmwareStatus { get; set; }
 
        }
 
        */
 
 
 
 
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static int NE_Ptr2String(IntPtr c, int len)
 
        {            
 
            string d = Marshal.PtrToStringAnsi(c);
 
            Console.WriteLine(d);
 
            return 0;
 
        }
 
 
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static int NE_Ptr2ByteArray(IntPtr c, int len)
 
        {
 
            System.Console.WriteLine(len);
 
            byte[] b 
= new byte[len
];  
            Marshal.Copy(c, b, 0, len);
 
            foreach (byte element in b)
 
            {
 
                System.Console.WriteLine(element);
 
            }
 
            System.Console.WriteLine();
 
            return b.Length;
 
        }
 
 
 
        //-----------------------------------
 
        // http://stackoverflow.com/questions/14934016/unmanaged-exports-with-arrays
 
        // https://github.com/kbilsted/NotepadPlusPlusPluginPack.Net/blob/master/Visual%20Studio%20Project%20Template%20C%23/PluginInfrastructure/UnmanagedExports.cs
 
        static IntPtr _unmanagedMemory = IntPtr.Zero;
 
        static int _unmanagedMemoryLength = 0;
 
 
 
        static void SD4_AllocateMemory(int len)
 
        {
 
 
 
            if (_unmanagedMemoryLength < len)
 
            {
 
                if (_unmanagedMemory != IntPtr.Zero)
 
                    Marshal.FreeHGlobal(_unmanagedMemory);
 
                _unmanagedMemory = Marshal.AllocHGlobal(len);
 
                _unmanagedMemoryLength = len;
 
 
 
            }
 
        }
 
 
 
 
 
        static ushort[] SD4_UShortBuffer = null;
 
        static ushort[] SD4_AllocateUshortBuffer(int len) {      
 
             if (SD4_UShortBuffer == null || SD4_UShortBuffer.Length < len) {
 
                    Array.Resize(ref SD4_UShortBuffer, len);
 
             }   
 
            return SD4_UShortBuffer;
 
        }
 
 
 
        static byte[] SD4_ByteBuffer = null;
 
        static byte[] SD4_AllocateByteBuffer(int len)
 
        {
 
            if (SD4_ByteBuffer == null || SD4_ByteBuffer.Length < len)
 
            {
 
                Array.Resize(ref SD4_ByteBuffer, len);
 
            }
 
            return SD4_ByteBuffer;
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static IntPtr NE_ByteArray2Ptr(ref IntPtr unmanagedArray, out int length)
 
        {
 
            var valueList 
= new[] { 1, 
2, 
3, 
3, 
2, 
1, 
12, 
11, 
10 };  
            System.Console.WriteLine("NE_ByteArray2Ptr");
 
 
 
            foreach (var element in valueList)
 
            {
 
                System.Console.WriteLine(element);
 
            }
 
            System.Console.WriteLine();
 
 
 
            length = valueList.Length;
 
            SD4_AllocateMemory(len);
 
            Marshal.Copy(valueList, 0, _unmanagedMemory, length);
 
            //
 
            //unmanagedArray = Marshal.AllocHGlobal(len);
 
            //Marshal.Copy(valueList, 0, unmanagedArray, length);
 
            return _unmanagedMemory;
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static int NE_ByteArray2Ptr1(ref IntPtr dest, ref int len)
 
        //static int NE_ByteArray2Ptr( ref byte[] src, ref int len)
 
        {
 
            len = 5;
 
            //Marshal.AllocHGlobal(len);
 
            byte[] src 
= new byte[len
];  
            for (int i = 0; i < len; i++)
 
            {
 
                src[i] = Convert.ToByte(i);
 
                //Marshal.WriteByte(dest, i, src[i] );
 
            }
 
            System.Console.WriteLine("NE_ByteArray2Ptr");
 
            System.Console.WriteLine(len);
 
            foreach (byte element in src)
 
            {
 
                System.Console.WriteLine(element);
 
            }
 
            System.Console.WriteLine();
 
 
 
            // Marshal.Copy(src, 0, dest, len);
 
 
 
            return src.Length;
 
        }
 
 
 
 
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static int NE_String2Ptr(ref IntPtr c)
 
        {
 
 
 
 
 
 
 
            // Copy the array to unmanaged memory.
 
            //c = Marshal.StringToHGlobalAnsi(d);
 
            string inputStr = Marshal.PtrToStringAnsi(c);
 
            Console.ForegroundColor = ConsoleColor.Green;
 
            Console.WriteLine(inputStr);
 
 
 
 
 
            string outputStr = "NE_String2Ptr";
 
            Console.ForegroundColor = ConsoleColor.Red;
 
            Console.WriteLine(outputStr);
 
            Console.ForegroundColor = ConsoleColor.White;
 
 
 
            // http://stackoverflow.com/questions/21378132/export-managed-c-sharp-function-to-return-changed-char-parameter-to-unmanaged-c            
 
            byte[] outputBytes = Encoding.Default.GetBytes(outputStr);
 
            //problemi   Marshal.Copy(outputBytes, 0, c, outputBytes.Length);
 
 
 
 
 
            return outputStr.Length;
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static IntPtr NE_String()
 
        {
 
            string d = "NE_String";
 
 
 
 
 
            // Copy the array to unmanaged memory.
 
            //c = Marshal.StringToHGlobalAnsi(d);
 
 
 
            Console.ForegroundColor = ConsoleColor.Green;
 
            Console.WriteLine(d);
 
            Console.ForegroundColor = ConsoleColor.White;
 
 
 
            return Marshal.StringToHGlobalAnsi(d);
 
        }
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static IntPtr NE_UInt(ref int len)
 
        {
 
            len = 10;
 
            uint[] b 
= new uint[len
];  
            for (uint i = 0; i < len; i++)
 
            {
 
                b[i] = i;
 
            }
 
            //PrintBytes(b);
 
            IntPtr p = Marshal.AllocHGlobal(len * 4);
 
            Marshal.Copy((int[])(object)b, 0, p, len);
 
            return p;
 
        }
 
 
 
 
 
        [DllExport(CallingConvention = CallingConvention.Cdecl)]
 
        static void NE_Rainbow()
 
        {
 
            Console.ForegroundColor = ConsoleColor.Red;
 
            Console.Write('R');
 
            Console.ForegroundColor = ConsoleColor.DarkRed;
 
            Console.Write('a');
 
            Console.ForegroundColor = ConsoleColor.Yellow;
 
            Console.Write('i');
 
            Console.ForegroundColor = ConsoleColor.Green;
 
            Console.Write('n');
 
            Console.ForegroundColor = ConsoleColor.Cyan;
 
            Console.Write('b');
 
            Console.ForegroundColor = ConsoleColor.Blue;
 
            Console.Write('o');
 
            Console.ForegroundColor = ConsoleColor.Magenta;
 
            Console.Write('w');
 
 
 
            Console.ResetColor();
 
            Console.WriteLine();
 
        }
 
    }
 
}