Unloading a plugin in Unity3D

One of my new assignments was to develop a controller to SCN6 actuators to be implemented in a simulator.

After hours of work disassembling a Tmbscom.DLL to be used in a C++ test program, i finally got it working.

Converting this code to C#, was a bit trick, but fortunately someone else did the hard work of writing the functions of DLL in C#.

This code is related to a repository (“EC Hardware”) that was located at assembla.com. The author had this project as opensource. But unfortunately, the repository was deleted. But Google Cache help-me and i could retrieved it.

using UnityEngine;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;

namespace Driver_SCN5
{
    public class SCN5: MonoBehaviour
    {
		#region &&&&&&&&&&&&&&&&& IMPORT TMBSCOM &&&&&&&&&&&&&&&&&

        #region ############ COMUNICACIONES ############
        [DllImport("Tmbscom", EntryPoint = "_init_tmbs_config@24")]
        public static unsafe extern int init_tmbs_config(
                        string port,      // Port Name ( "COM1","COM2"etc. )
                        int baud,          // Baudrate( 4,5,6,7,11H,12H,13H,14H )
                        int nrt,           // Retry
                        bool reset,        //
                        bool automatic,    //
                        ref int axes_info     //
                        );
        [DllImport("TMBSCOM.dll", EntryPoint = "_close_tmbs@0")]
        public static unsafe extern int close_tmbs();

        [DllImport("TMBSCOM.dll", EntryPoint = "_get_current_baud@0")]
        public static unsafe extern int get_current_baud();

		[DllImport("TMBSCOM.dll", EntryPoint = "_init_tmbs@0")]
        public static unsafe extern int init_tmbs();

        #endregion

        #region ############ ESTADO ############

        [DllImport("TMBSCOM.dll", EntryPoint = "_get_tmbs_state@0")]
        public static unsafe extern int get_tmbs_state();

        [DllImport("TMBSCOM.dll", EntryPoint = "_get_sio_error@0")]
        public static unsafe extern int get_sio_error();

        [DllImport("TMBSCOM.dll", EntryPoint = "_check_pfin@4")]
        public static unsafe extern int check_pfin(int axis);

        [DllImport("TMBSCOM.dll", EntryPoint = "_check_status@4")]
        public static unsafe extern int check_status(int axis);

        [DllImport("TMBSCOM.dll", EntryPoint = "_check_alrm@4")]
        public static unsafe extern int check_alrm(int axis);

        [DllImport("TMBSCOM.dll", EntryPoint = "_reset_alarm@4")]
        public static unsafe extern int reset_alarm(int axis);

        [DllImport("TMBSCOM.dll")]
        public static unsafe extern int read_param(int axis, ref COMPACK dst);

        [DllImport("TMBSCOM.dll", EntryPoint = "_set_son@4")]
        public static unsafe extern int set_son(int axis);

        [DllImport("TMBSCOM.dll", EntryPoint = "_set_soff@4")]
        public static unsafe extern int set_soff(int axis);

        #endregion

        #region ############ MOVIMIENTO ############

        [DllImport("TMBSCOM.dll", CallingConvention = CallingConvention.Winapi, EntryPoint = "_move_point@8")]
        public static unsafe extern int move_point(int axis, int point);

        [DllImport("TMBSCOM.dll", EntryPoint = "_move_org@8")]
        public static unsafe extern int move_org(int axis, int position);

        [DllImport("TMBSCOM.dll")]
        public static unsafe extern int move_abs(int axis, int position);

        [DllImport("TMBSCOM.dll")]
        public static unsafe extern int move_jog(int axis, int distance);

        [DllImport("TMBSCOM.dll", EntryPoint = "_move_inc@8")]
        public static unsafe extern int move_inc(int axis, int distance);

        [DllImport("TMBSCOM.dll", EntryPoint = "_move_rotate@16")]
        public static unsafe extern int move_rotate(int axis, int dir, int velocidad, int aceleracion);

        #endregion

        #region ############ PARAMETROS ############

        [DllImport("TMBSCOM.dll", EntryPoint = "_write_velocity@12")]
        public static unsafe extern int write_velocity(int axis, int vcmd, int acmd);

        [DllImport("TMBSCOM.dll", EntryPoint = "_select_svparm@12")]
        public static unsafe extern int select_svparm(int axis, int gain_sel, int svparm);

        [DllImport("TMBSCOM.dll", EntryPoint = "_write_trqlim@12")]
        public static unsafe extern int write_trqlim(int axis, int atstop, int atmovement);

        [DllImport("TMBSCOM.dll", EntryPoint = "_write_inpos@8")]
        public static unsafe extern int write_inpos(int axis, int width);

        [DllImport("TMBSCOM.dll", EntryPoint = "_write_point@12")]
        public static unsafe extern int write_point(int axis, int point, ref COMPACK src);

        [DllImport("TMBSCOM.dll", EntryPoint = "_read_point@12")]
        public extern unsafe static int read_point(int axis, int point, ref COMPACK dst);

        [DllImport("TMBSCOM.dll")]
        public static unsafe extern int load_param(int axis);

        [DllImport("TMBSCOM.dll")]
        public static unsafe extern int write_param(int axis, ref COMPACK src);

        [DllImport("TMBSCOM.dll")]
        public static unsafe extern int read_svmem(int axis, int address, ref int dst);

        [DllImport("TMBSCOM.dll")]
        public static unsafe extern int write_svmem(int axis, int address, ref int dst);

        public struct COMPACK
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 31)]
            public long[] address;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 31)]
            public long[] data;

            public void initialize()
            {
                address = new long[31];
                data = new long[31];

                for (int i = 0; i < address.Length; i++)
                    address[i] = i;
            }
        }

        public const int TMBS_NO_EXIST = 0;
        public const int TMBS_INITIAL = 1;
        public const int TMBS_INIT_ERROR = 2;
        public const int TMBS_OPENING = 3;
        public const int TMBS_RUNNING = 4;
        public const int SIO_DONE = 1;
        public const int SIO_ERROR = 0;

        public static COMPACK newPacket;
        public int[] axes_info;

        #endregion

        #endregion

        #region &&&&&&&&&&&&&&&&& CONSTRUCTOR &&&&&&&&&&&&&&&&&
        public SCN5()
        {
            axes_info = new int[16];
            newPacket.initialize();
        }
        #endregion

        #region &&&&&&&&&&&&&&&&& METODOS PUBLICOS &&&&&&&&&&&&&&&&&

        #region ############ COMUNICACIONES ############

        public int Start_Comunnication(String port, int repeat)
        {
            int i = 0;
            int j = repeat;

            for (i = 0; i < 16; i++)
                axes_info[i] = -1;

            axes_info[0] = 0; // Axis#0 is used
			axes_info[1] = 0;
            /*while (init_tmbs_config(port, Convert.ToInt16("14", 16), 3, false, true, ref axes_info[0]) != 1 && j != 0)
            {
                if (get_tmbs_state() == TMBS_INIT_ERROR)
                    return get_tmbs_state();
                j--;
            }
            j = repeat;
            while (get_tmbs_state() <= TMBS_OPENING && j != 0)
            {
                Thread.Sleep(500);
                j--;
            }*/

			while (init_tmbs() != 1 && j != 0) {
				Thread.Sleep(5);
				if (get_tmbs_state() == 2) {
					break;
				}
				j--;
			}

            return get_tmbs_state();
        }

        public int Close_Communications()
        {
            return close_tmbs();
        }

        public int Get_CurrentBaud()
        {
            return get_current_baud();
        }

        public int Init_Calibration(int axis)
        {
            int status = SIO_ERROR;
            if (get_tmbs_state() == TMBS_RUNNING)
            {
                status = move_point(axis, -1000);
                Thread.Sleep(1000);
                move_abs(axis, -10000);
            }
            return status;
        }

        #endregion

        #region ############ ESTADO ############

        public int Get_State()
        {
            return get_tmbs_state();
        }

        public int Get_SIO_Error()
        {
            return get_sio_error();
        }

        public int Check_Pfin(int axis)
        {
            return check_pfin(axis);
        }

        public int Check_Status(int axis)
        {
            return check_status(axis);
        }

        public int Check_Alarm(int axis)
        {
            return check_alrm(axis);
        }

        public int Reset_Alarm(int axis)
        {
            return reset_alarm(axis);
        }

        public int Servo_On(int axis)
        {
            return set_son(axis);
        }

        public int Servo_Off(int axis)
        {
            return set_soff(axis);
        }
        #endregion

        #region ############ MOVIMIENTO ############
        public int Move_Point(int axis, int point)
        {
            return move_point(axis, point);
        }

        public int Move_Abs(int axis, int position)
        {
            return move_abs(axis, position);
        }

        public int Move_Inc(int axis, int distance)
        {
            return move_inc(axis, distance);
        }

        public int Move_ORG(int axis, int mode)
        {
            return move_org(axis, mode);
        }

        public int Move_Rotate(int axis, int dir, int velocidad, int aceleracion)
        {
            return move_rotate(axis, dir, velocidad, aceleracion);
        }

        public int Move_JOG(int axis, int distance)
        {
            return move_jog(axis, distance);
        }
        #endregion

        #region ############ PARAMETROS ############
        public int Write_Velocity(int axis, int velocidad, int aceleracion)
        {
            return write_velocity(axis, velocidad, aceleracion);
        }

        public int Write_GainServo(int axis, int gain_sel, int svparm)
        {
            return select_svparm(axis, gain_sel, svparm);
        }

        public int Write_TrqLim(int axis, int atstop, int atmovement)
        {
            return write_trqlim(axis, atstop, atmovement);
        }

        public int Write_Tolerance(int axis, int width)
        {
            return write_inpos(axis, width);
        }

        public int Read_Position(int axis)
        {
            int bank1 = Convert.ToInt16("29", 16);
            int bank2 = Convert.ToInt16("29", 16);
            int dataLoc = Convert.ToInt16("7400", 16);
            read_svmem(axis, dataLoc, ref bank1);
            int retVal = bank1;
            return retVal;
        }

        public int Read_Code_RZONE(int axis)
        {
            int bank1 = Convert.ToInt16("29", 16);
            int bank2 = Convert.ToInt16("12", 16);
            int dataLoc = Convert.ToInt16("5", 16);
            read_svmem(axis, dataLoc, ref bank1);
            int retVal = bank1;

            //write_svmem(axis, dataLoc, ref bank2);

            return retVal;
        }

        public int Read_Code_FZONE(int axis)
        {
            int bank1 = Convert.ToInt16("29", 16);
            int bank2 = Convert.ToInt16("12", 16);
            int dataLoc = Convert.ToInt16("4", 16);
            read_svmem(axis, dataLoc, ref bank1);
            int retVal = bank1;

            //write_svmem(axis, dataLoc, ref bank2);

            return retVal;
        }
        #endregion

        #endregion

        #region &&&&&&&&&&&&&&&&& METODOS PRIVADOS &&&&&&&&&&&&&&&&&
        private long getLongValue(string positionStr)
        {
            bool isNegative;
            string hexRep;
            long longRep;
            long position = Convert.ToInt64(positionStr, 10);

            if (position < 0)
                isNegative = true;
            else
                isNegative = false;

            if (isNegative)
            {
                //Convert to hex to view in word format
                hexRep = Convert.ToString(position, 16);
                //Get least significant double word
                hexRep = hexRep.Substring(hexRep.Length - 8, 8);
                //swap double words
                hexRep = hexRep.PadRight(16, '0');
                //convert to number
                longRep = Convert.ToInt64(hexRep, 16);
                return longRep;
            }
            else
            {
                //converts integer to a hex value
                hexRep = Convert.ToString(position, 16);
                //pad the value to ensure correct offset
                //since the positive numbers have leading 0's we do not need to fill the full 64 bits
                hexRep = hexRep + "00000000";
                longRep = Convert.ToInt64(hexRep, 16);
                return longRep;
            }
        }
        private int getIntValue(long position)
        {
            string binaryRep;
            string hexRep;
            int intRep;
            bool isNegative;
            string onesComp;
            long onesCompInt;

            binaryRep = Convert.ToString(position, 2);

            //Check to see that the length is 64 bits, and check the sign bit(msb) to see if its negative
            //In the event that the number is positive, the msb=0 and will normally be left out when
            //converted to an integer
            if (binaryRep.Length == 64 && binaryRep.Substring(0, 1) == "1")
                isNegative = true;
            else
            {
                //Check to see if the position is 0
                if (binaryRep.Length == 1)
                    return 0;
                isNegative = false;
            }

            if (isNegative)
            {
                //To get actual decimal value, we must convert from the one's compliment representation
                //To ones compliment switch 0's to 1's and 1's to zeros, then add 1
                onesComp = binaryRep.Replace("0", "2");
                onesComp = onesComp.Replace("1", "0");
                onesComp = onesComp.Replace("2", "1");
                onesCompInt = Convert.ToInt64(onesComp, 2);
                onesCompInt = onesCompInt + 1;
                //This is now the unsigned value
                hexRep = Convert.ToString(onesCompInt, 16);
                //There is an extra word (8 bits) that we must remove
                hexRep = hexRep.Remove(hexRep.Length - 8, 8);
                intRep = Convert.ToInt16(hexRep, 16);
                //Add the sign back on
                intRep = (intRep * -1);
                return intRep;
            }
            else
            {
                //Convert the binary representation to HEX
                hexRep = Convert.ToString(Convert.ToInt64(binaryRep, 2), 16);
                //Remove the extra word (8 Bits)
                hexRep = hexRep.Remove(hexRep.Length - 8, 8);
                //Convert back to a decimal
                intRep = Convert.ToInt32(hexRep, 16);
                return intRep;
            }
        }
        #endregion
    }
}

The problem: Using this code in a Unity3D project created a known and old problem. You could do only one access. The second attempt result in IDE lock.

Reading about a similar problem in this post.

I could find an excellent way to dinamically invoke a C++ DLL using C#.

For thoses who program in MFC Win32 using C++, should known the LoadLibrary, FreeLibrary. Essential to solve this problem with Tmbscom.DLL.

As a result, there are two DLLs, one that will be accessed from Unity3D (Driver_SCN5.DLL) to wrap the Tmbscom.DLL.

A converted source in C# used as a plugin for Unity3D:

using UnityEngine;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;

namespace Driver_SCN5
{
    public class SCN5: MonoBehaviour
    {

		int hModule;

        [DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]
        static extern int LoadLibrary(
        [MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);

        [DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
        static extern IntPtr GetProcAddress( int hModule,
        [MarshalAs(UnmanagedType.LPStr)] string lpProcName);

        [DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
        static extern bool FreeLibrary(int hModule);

		#region &&&&&&&&&&&&&&&&& IMPORT TMBSCOM &&&&&&&&&&&&&&&&&

        #region ############ COMUNICACIONES ############

		public delegate int DLL_INIT_TMBS_CONFIG(
						string port,      // Port Name ( "COM1","COM2"etc. )
                        int baud,          // Baudrate( 4,5,6,7,11H,12H,13H,14H )
                        int nrt,           // Retry
                        bool reset,        //
                        bool automatic,    //
                        ref int axes_info     //
                        );
		DLL_INIT_TMBS_CONFIG init_tmbs_config;

		public delegate int DLL_CLOSE_TMBS();
		DLL_CLOSE_TMBS close_tmbs;

		public delegate int DLL_GET_CURRENT_BAUD();
		DLL_GET_CURRENT_BAUD get_current_baud;

		public delegate int DLL_INIT_TMBS();
		DLL_INIT_TMBS init_tmbs;

        #endregion

        #region ############ ESTADO ############

		public delegate int DLL_GET_TMBS_STATE();
		DLL_GET_TMBS_STATE get_tmbs_state;

		public delegate int DLL_GET_SIO_ERROR();
		DLL_GET_SIO_ERROR get_sio_error;

		public delegate int DLL_CHECK_PFIN(int axis);
		DLL_CHECK_PFIN check_pfin;

		public delegate int DLL_CHECK_STATUS(int axis);
        DLL_CHECK_STATUS check_status;

		public delegate int DLL_CHECK_ALRM(int axis);
        DLL_CHECK_ALRM check_alrm;

		public delegate int DLL_RESET_ALARM(int axis);
        DLL_RESET_ALARM reset_alarm;

		/*NAO ESTAVA COMPLETA VER CODIGO ORIGINAL*/
        public delegate int DLL_READ_PARAM(int axis, ref COMPACK dst);
		DLL_READ_PARAM read_param;

		public delegate int DLL_SET_SON(int axis);
        DLL_SET_SON set_son;

		public delegate int DLL_SET_SOFF(int axis);
        DLL_SET_SOFF set_soff;

        #endregion

        #region ############ MOVIMIENTO ############

		[UnmanagedFunctionPointer(CallingConvention.Winapi)]
		public delegate int DLL_MOVE_POINT(int axis, int point);
		DLL_MOVE_POINT move_point;

		public delegate int DLL_MOVE_ORG(int axis, int position);
		DLL_MOVE_ORG move_org;

		public delegate int DLL_MOVE_ABS(int axis, int position);
		DLL_MOVE_ABS move_abs;

        public delegate int DLL_MOVE_JOG(int axis, int distance);
		DLL_MOVE_JOG move_jog;

		public delegate int DLL_MOVE_INC(int axis, int distance);
        DLL_MOVE_INC move_inc;

		public delegate int DLL_MOVE_ROTATE(int axis, int dir, int speed, int accel);
        DLL_MOVE_ROTATE move_rotate;

        #endregion

        #region ############ PARAMETROS ############

		public delegate int DLL_WRITE_VELOCITY(int axis, int vcmd, int acmd);
        DLL_WRITE_VELOCITY write_velocity;

        public delegate int DLL_SELECT_SVPARM(int axis, int gain_sel, int svparm);
        DLL_SELECT_SVPARM select_svparm;

        public delegate int DLL_WRITE_TRQLIM(int axis, int atstop, int atmovement);
        DLL_WRITE_TRQLIM write_trqlim;

        public delegate int DLL_WRITE_INPOS(int axis, int width);
        DLL_WRITE_INPOS write_inpos;

		public delegate int DLL_WRITE_POINT(int axis, int point, ref COMPACK src);
        DLL_WRITE_POINT write_point;

		public delegate int DLL_READ_POINT(int axis, int point, ref COMPACK dst);
        DLL_READ_POINT read_point;

        public delegate int DLL_LOAD_PARAM(int axis);
        DLL_LOAD_PARAM load_param;

		public delegate int DLL_WRITE_PARAM(int axis, ref COMPACK src);
        DLL_WRITE_PARAM write_param;

		public delegate int DLL_READ_SVMEM(int axis, int address, ref int dst);
        DLL_READ_SVMEM read_svmem;

		public delegate int DLL_WRITE_SVMEM(int axis, int address, ref int dst);
        DLL_WRITE_SVMEM write_svmem;

        public struct COMPACK
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 31)]
            public long[] address;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 31)]
            public long[] data;

            public void initialize()
            {
                address = new long[31];
                data = new long[31];

                for (int i = 0; i < address.Length; i++)
                    address[i] = i;
            }
        }

        public const int TMBS_NO_EXIST = 0;
        public const int TMBS_INITIAL = 1;
        public const int TMBS_INIT_ERROR = 2;
        public const int TMBS_OPENING = 3;
        public const int TMBS_RUNNING = 4;
        public const int SIO_DONE = 1;
        public const int SIO_ERROR = 0;

        public static COMPACK newPacket;
        public int[] axes_info;

        #endregion

        #endregion

        #region &&&&&&&&&&&&&&&&& CONSTRUCTOR &&&&&&&&&&&&&&&&&
        public SCN5()
        {
			hModule = LoadLibrary("Tmbscom.DLL");

			init_tmbs = (DLL_INIT_TMBS) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_init_tmbs@0"), typeof(DLL_INIT_TMBS));
			close_tmbs = (DLL_CLOSE_TMBS) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_close_tmbs@0"), typeof(DLL_CLOSE_TMBS));
			move_point = (DLL_MOVE_POINT) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_move_point@8"), typeof(DLL_MOVE_POINT));
			get_tmbs_state = (DLL_GET_TMBS_STATE) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_get_tmbs_state@0"), typeof(DLL_GET_TMBS_STATE));
			init_tmbs_config = (DLL_INIT_TMBS_CONFIG) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_init_tmbs_config@24"), typeof(DLL_INIT_TMBS_CONFIG));
			set_son = (DLL_SET_SON) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_set_son@4"), typeof(DLL_SET_SON));
			set_soff = (DLL_SET_SOFF) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_set_soff@4"), typeof(DLL_SET_SOFF));
			move_org = (DLL_MOVE_ORG) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_move_org@8"), typeof(DLL_MOVE_ORG));
			move_abs = (DLL_MOVE_ABS) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_move_abs@8"), typeof(DLL_MOVE_ABS));
			move_jog = (DLL_MOVE_JOG) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_move_jog@8"), typeof(DLL_MOVE_JOG));
			move_inc = (DLL_MOVE_INC) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_move_inc@8"), typeof(DLL_MOVE_INC));
			move_rotate = (DLL_MOVE_ROTATE) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_move_rotate@16"), typeof(DLL_MOVE_ROTATE));
			write_velocity = (DLL_WRITE_VELOCITY) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_write_velocity@12"), typeof(DLL_WRITE_VELOCITY));
			select_svparm = (DLL_SELECT_SVPARM) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_select_svparm@12"), typeof(DLL_SELECT_SVPARM));
			write_trqlim = (DLL_WRITE_TRQLIM) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_write_trqlim@12"), typeof(DLL_WRITE_TRQLIM));
			write_inpos = (DLL_WRITE_INPOS) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_write_inpos@8"), typeof(DLL_WRITE_INPOS));
			write_point = (DLL_WRITE_POINT) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_write_point@12"), typeof(DLL_WRITE_POINT));
			read_point = (DLL_READ_POINT) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_read_point@12"), typeof(DLL_READ_POINT));
			load_param = (DLL_LOAD_PARAM) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_load_param@4"), typeof(DLL_LOAD_PARAM));
			write_param = (DLL_WRITE_PARAM) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_write_param@8"), typeof(DLL_WRITE_PARAM));
			read_svmem = (DLL_READ_SVMEM) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_read_svmem@12"), typeof(DLL_READ_SVMEM));
			write_svmem = (DLL_WRITE_SVMEM) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_write_svmem@12"), typeof(DLL_WRITE_SVMEM));
			get_current_baud = (DLL_GET_CURRENT_BAUD) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_get_current_baud@0"), typeof(DLL_GET_CURRENT_BAUD));
			get_sio_error = (DLL_GET_SIO_ERROR) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_get_sio_error@0"), typeof(DLL_GET_SIO_ERROR));
			check_pfin = (DLL_CHECK_PFIN) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_check_pfin@4"), typeof(DLL_CHECK_PFIN));
			check_status = (DLL_CHECK_STATUS) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_check_status@4"), typeof(DLL_CHECK_STATUS));
			check_alrm = (DLL_CHECK_ALRM) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_check_alrm@4"), typeof(DLL_CHECK_ALRM));
			reset_alarm = (DLL_RESET_ALARM) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_reset_alarm@4"), typeof(DLL_RESET_ALARM));
			read_param = (DLL_READ_PARAM) Marshal.GetDelegateForFunctionPointer(GetProcAddress(hModule, "_read_param@8"), typeof(DLL_READ_PARAM));

            axes_info = new int[16];
            newPacket.initialize();
        }
        #endregion

        #region &&&&&&&&&&&&&&&&& METODOS PUBLICOS &&&&&&&&&&&&&&&&&

        #region ############ COMUNICACIONES ############

        public int Start_Comunnication(String port, int repeat)
        {
            int i = 0;
            int j = repeat;

            for (i = 0; i < 16; i++)
                axes_info[i] = -1;

            axes_info[0] = 0; // Axis#0 is used
			axes_info[1] = 0;
            while (init_tmbs_config(port, Convert.ToInt16("14", 16), 3, false, true, ref axes_info[0]) != 1 && j != 0)
            {
                if (get_tmbs_state() == TMBS_INIT_ERROR)
                    return get_tmbs_state();
                j--;
            }
            j = repeat;
            while (get_tmbs_state() <= TMBS_OPENING && j != 0)
            {
                Thread.Sleep(500);
                j--;
            }

            return get_tmbs_state();
        }

        public int Close_Communications()
        {
			int result = close_tmbs();

			FreeLibrary(hModule);

            return result;
        }

        public int Get_CurrentBaud()
        {
            return get_current_baud();
        }

        public int Init_Calibration(int axis)
        {
            int status = SIO_ERROR;
            if (get_tmbs_state() == TMBS_RUNNING)
            {
                status = move_point(axis, -1000);
                Thread.Sleep(1000);
                move_abs(axis, -10000);
            }
            return status;
        }

        #endregion

        #region ############ ESTADO ############

        public int Get_State()
        {
            return get_tmbs_state();
        }

        public int Get_SIO_Error()
        {
            return get_sio_error();
        }

        public int Check_Pfin(int axis)
        {
            return check_pfin(axis);
        }

        public int Check_Status(int axis)
        {
            return check_status(axis);
        }

        public int Check_Alarm(int axis)
        {
            return check_alrm(axis);
        }

        public int Reset_Alarm(int axis)
        {
            return reset_alarm(axis);
        }

        public int Servo_On(int axis)
        {
            return set_son(axis);
        }

        public int Servo_Off(int axis)
        {
            return set_soff(axis);
        }
        #endregion

        #region ############ MOVIMIENTO ############
        public int Move_Point(int axis, int point)
        {
            return move_point(axis, point);
        }

        public int Move_Abs(int axis, int position)
        {
            return move_abs(axis, position);
        }

        public int Move_Inc(int axis, int distance)
        {
            return move_inc(axis, distance);
        }

        public int Move_ORG(int axis, int mode)
        {
            return move_org(axis, mode);
        }

        public int Move_Rotate(int axis, int dir, int velocidad, int aceleracion)
        {
            return move_rotate(axis, dir, velocidad, aceleracion);
        }

        public int Move_JOG(int axis, int distance)
        {
            return move_jog(axis, distance);
        }
        #endregion

        #region ############ PARAMETROS ############
        public int Write_Velocity(int axis, int velocidad, int aceleracion)
        {
            return write_velocity(axis, velocidad, aceleracion);
        }

        public int Write_GainServo(int axis, int gain_sel, int svparm)
        {
            return select_svparm(axis, gain_sel, svparm);
        }

        public int Write_TrqLim(int axis, int atstop, int atmovement)
        {
            return write_trqlim(axis, atstop, atmovement);
        }

        public int Write_Tolerance(int axis, int width)
        {
            return write_inpos(axis, width);
        }

        public int Read_Position(int axis)
        {
            int bank1 = Convert.ToInt16("29", 16);
            int bank2 = Convert.ToInt16("29", 16);
            int dataLoc = Convert.ToInt16("7400", 16);
            read_svmem(axis, dataLoc, ref bank1);
            int retVal = bank1;
            return retVal;
        }

        public int Read_Code_RZONE(int axis)
        {
            int bank1 = Convert.ToInt16("29", 16);
            int bank2 = Convert.ToInt16("12", 16);
            int dataLoc = Convert.ToInt16("5", 16);
            read_svmem(axis, dataLoc, ref bank1);
            int retVal = bank1;

            //write_svmem(axis, dataLoc, ref bank2);

            return retVal;
        }

        public int Read_Code_FZONE(int axis)
        {
            int bank1 = Convert.ToInt16("29", 16);
            int bank2 = Convert.ToInt16("12", 16);
            int dataLoc = Convert.ToInt16("4", 16);
            read_svmem(axis, dataLoc, ref bank1);
            int retVal = bank1;

            //write_svmem(axis, dataLoc, ref bank2);

            return retVal;
        }
        #endregion

        #endregion

        #region &&&&&&&&&&&&&&&&& METODOS PRIVADOS &&&&&&&&&&&&&&&&&
        private long getLongValue(string positionStr)
        {
            bool isNegative;
            string hexRep;
            long longRep;
            long position = Convert.ToInt64(positionStr, 10);

            if (position < 0)
                isNegative = true;
            else
                isNegative = false;

            if (isNegative)
            {
                //Convert to hex to view in word format
                hexRep = Convert.ToString(position, 16);
                //Get least significant double word
                hexRep = hexRep.Substring(hexRep.Length - 8, 8);
                //swap double words
                hexRep = hexRep.PadRight(16, '0');
                //convert to number
                longRep = Convert.ToInt64(hexRep, 16);
                return longRep;
            }
            else
            {
                //converts integer to a hex value
                hexRep = Convert.ToString(position, 16);
                //pad the value to ensure correct offset
                //since the positive numbers have leading 0's we do not need to fill the full 64 bits
                hexRep = hexRep + "00000000";
                longRep = Convert.ToInt64(hexRep, 16);
                return longRep;
            }
        }
        private int getIntValue(long position)
        {
            string binaryRep;
            string hexRep;
            int intRep;
            bool isNegative;
            string onesComp;
            long onesCompInt;

            binaryRep = Convert.ToString(position, 2);

            //Check to see that the length is 64 bits, and check the sign bit(msb) to see if its negative
            //In the event that the number is positive, the msb=0 and will normally be left out when
            //converted to an integer
            if (binaryRep.Length == 64 && binaryRep.Substring(0, 1) == "1")
                isNegative = true;
            else
            {
                //Check to see if the position is 0
                if (binaryRep.Length == 1)
                    return 0;
                isNegative = false;
            }

            if (isNegative)
            {
                //To get actual decimal value, we must convert from the one's compliment representation
                //To ones compliment switch 0's to 1's and 1's to zeros, then add 1
                onesComp = binaryRep.Replace("0", "2");
                onesComp = onesComp.Replace("1", "0");
                onesComp = onesComp.Replace("2", "1");
                onesCompInt = Convert.ToInt64(onesComp, 2);
                onesCompInt = onesCompInt + 1;
                //This is now the unsigned value
                hexRep = Convert.ToString(onesCompInt, 16);
                //There is an extra word (8 bits) that we must remove
                hexRep = hexRep.Remove(hexRep.Length - 8, 8);
                intRep = Convert.ToInt16(hexRep, 16);
                //Add the sign back on
                intRep = (intRep * -1);
                return intRep;
            }
            else
            {
                //Convert the binary representation to HEX
                hexRep = Convert.ToString(Convert.ToInt64(binaryRep, 2), 16);
                //Remove the extra word (8 Bits)
                hexRep = hexRep.Remove(hexRep.Length - 8, 8);
                //Convert back to a decimal
                intRep = Convert.ToInt32(hexRep, 16);
                return intRep;
            }
        }
        #endregion
    }
}

With this approuch the Unity3D Editor is working fine, to load and unload the Actuators DLL.

5 comentários em “Unloading a plugin in Unity3D

Deixe um comentário