locked
C++ services MRDS 4 RRS feed

  • Question

  • hi all,

    I have installed the new version of MRDS, and I am trying to create a service using the command line dssnewservice which returns the following result for the language parameter: /l:Cpp

    Only Csharp is supported

    I am trying that to use native c++ libraries in my work.

    thanks

    Saturday, March 10, 2012 2:02 PM

Answers

  • CPP has been deprecated from support in Robotics Developer Studio.  Only C# is supported in RDS4.  What I suggest, and consequently have done quite often, is to utilize an Interop layer between your CPP native libraries and your managed C# classes, explicitly a DSS service. 

    See:  http://PInvoke.net or http://msdn.microsoft.com/en-us/library/aa446536.aspx or http://msdn.microsoft.com/en-us/library/ms235282.aspx or http://msdn.microsoft.com/en-us/magazine/cc164123.aspx or http://www.microsoft.com/indonesia/msdn/pinvoke.aspx or http://msdn.microsoft.com/en-us/library/aa288468(v=VS.71).aspx

    This is generally how I do Interop access to native methods from a wrapped managed C# class.  I'll let you integrate the resulting managed C# class into your DSS service.

    namespace xxxInteropUtilities
    {
        using System;
        using System.Runtime.InteropServices;
     
        /// <summary>
        /// PInvoke Native Wrapper for handling xxx native binary
        /// </summary>
        public static class xxxInteropUtilities
        {
            /// <summary>
            /// Wrapper Class for NativeMethods to xxx native binary
            /// </summary>
            internal static class NativeMethods
            {
                [DllImport("xxxNativeBinary.dll")]
                public static extern int OpenHandle(
                    [Inuint clientVersion,
                    [InOutIntPtr reserved,
                    [Outout uint negotiatedVersion,
                    [Outout xxxSafeHandle clientHandle);
     
                [DllImport("xxxNativeBinary.dll")]
                public static extern int CloseHandle(
                    [InIntPtr clientHandle,
                    [InOutIntPtr reserved);
     
                [DllImport("xxxNativeBinary.dll")]
                public static extern void FreeMemory([InIntPtr memory);
     
                [DllImport("xxxNativeBinary.dll")]
                public static extern int DoSomethingNative(
                    [InxxxSafeHandle clientHandle,
                    [InMarshalAs(UnmanagedType.LPStruct)] Guid nativeGuid,
                    [InInt16 flags,
                    [InOutIntPtr reserved,
                    [Outout IntPtr nativeDataResult);
            }
     
            /// <summary>
            /// Additional struct and enum definitions for interfacing to xxx native binary go here
            /// </summary>
        }
        
        /// <summary>
        /// Class that provides a SafeHandle for the xxx native binary ClientHandle
        /// </summary>
        public sealed class xxxSafeHandle : SafeHandle
        {
            /// <summary>
            /// Class that provides a SafeHandle for the xxx native binary
            /// </summary>
            public xxxSafeHandle()
                : base(IntPtr.Zero, true)
            {
                return;
            }
     
            /// <summary>
            /// Returns a value to determine if internal IntPtr is still valid.
            /// </summary>
            public override bool IsInvalid
            {
                get
                {
                    return this.handle == IntPtr.Zero;
                }
            }
     
            /// <summary>
            /// Clean up the contained resource
            /// </summary>
            /// <returns>Success or Failure during CloseHandle</returns>
            protected override bool ReleaseHandle()
            {
                return xxxInteropUtilities.NativeMethods.CloseHandle(this.handle, IntPtr.Zero) == 0;
            }
        }
     
        /// <summary>
        /// Managed Class for xxxClient wrapping the NativeMethods for xxxNativeBinary.dll
        /// </summary>
        public class xxxClient : IDisposable
        {
            /// <summary>
            /// SafeHandle for managing NativeMethods wrapper for xxxNativeBinary.dll
            /// </summary>
            private xxxSafeHandle xxxHandle;
            
            /// <summary>
            /// Track whether Dispose has been called.
            /// </summary>
            private bool disposed = false;
            
            /// <summary>
            /// Gets the IntPtr for the xxxHandle to xxxNativeBinary.dll
            /// </summary>
            public xxxSafeHandle XxxHandle
            {
                get
                {
                    return this.xxxHandle;
                }
            }
            
            /// <summary>
            /// Constructor which sets up the xxxNativeBinary.dll NativeMethods
            /// </summary>
            public xxxClient()
            {
                this.xxxHandle = new xxxSafeHandle();
     
                uint clientVersion = 2;
                uint negotiatedVersion = 0;
                
                xxxInteropUtilities.NativeMethods.OpenHandle(clientVersion, IntPtr.Zero, out negotiatedVersion, out this.xxxHandle);
            }
     
            /// <summary> 
            /// Destructor which triggers the Dispose method 
            /// </summary> 
            ~xxxClient()
            {
                this.Dispose(false);
            }
     
            /// <summary> 
            /// Implement IDisposable. 
            /// Do not make this method virtual. 
            /// A derived class should not be able to override this method. 
            /// </summary> 
            public void Dispose()
            {
                this.Dispose(true);
     
                // This object will be cleaned up by the Dispose method. 
                // Therefore, you should call GC.SupressFinalize to 
                // take this object off the finalization queue 
                // and prevent finalization code for this object 
                // from executing a second time. 
                GC.SuppressFinalize(this);
            }
     
            /// <summary> 
            /// Dispose(bool disposing) executes in two distinct scenarios. 
            /// If disposing equals true, the method has been called directly 
            /// or indirectly by a user's code. Managed and unmanaged resources 
            /// can be disposed. 
            /// If disposing equals false, the method has been called by the 
            /// runtime from inside the finalizer and you should not reference 
            /// other objects. Only unmanaged resources can be disposed. 
            /// </summary> 
            /// <param name="disposing">Determines the phase of Dispose to run.</param> 
            protected virtual void Dispose(bool disposing)
            {
                if (!this.disposed)
                {
                    // If disposing equals true, dispose all managed 
                    // and unmanaged resources. 
                    if (disposing)
                    {
                        // Dispose managed types                     
                        this.xxxHandle.Dispose();
                    }
     
                    // Call the appropriate methods to clean up 
                    // unmanaged resources here. 
                    // If disposing is false, 
                    // only the following code is executed.
     
                    // Note disposing has been done. 
                    this.disposed = true;
                }
            }
     
            /// <summary>
            /// Example Method which Does Something Native
            /// </summary>
            /// <returns>The native return value</returns>
            public int DoSomethingNative()
            {
                int nativeResult = -1;
                IntPtr nativeMemory;
     
                int cmdSuccess = xxxInteropUtilities.NativeMethods.DoSomethingNative(this.xxxHandle, new Guid("Example Native Method Guid"), 0, IntPtr.Zero, out nativeMemory);
                if (cmdSuccess != 0)
                {
                    throw new Exception(cmdSuccess.ToString());
                }
     
                try
                {
                    //do something extra in managed land with the native data residing in nativeMemory...
                }
                finally
                {
                    //always wrap your access to the nativeMemory in a try/finally so that you *always* clean-up the native memory before exiting.
                    xxxInteropUtilities.NativeMethods.FreeMemory(nativeMemory);
                }
     
                return nativeResult;
            }
        }
    }
    
    Tuesday, March 13, 2012 6:05 PM
    Moderator

All replies

  • CPP has been deprecated from support in Robotics Developer Studio.  Only C# is supported in RDS4.  What I suggest, and consequently have done quite often, is to utilize an Interop layer between your CPP native libraries and your managed C# classes, explicitly a DSS service. 

    See:  http://PInvoke.net or http://msdn.microsoft.com/en-us/library/aa446536.aspx or http://msdn.microsoft.com/en-us/library/ms235282.aspx or http://msdn.microsoft.com/en-us/magazine/cc164123.aspx or http://www.microsoft.com/indonesia/msdn/pinvoke.aspx or http://msdn.microsoft.com/en-us/library/aa288468(v=VS.71).aspx

    This is generally how I do Interop access to native methods from a wrapped managed C# class.  I'll let you integrate the resulting managed C# class into your DSS service.

    namespace xxxInteropUtilities
    {
        using System;
        using System.Runtime.InteropServices;
     
        /// <summary>
        /// PInvoke Native Wrapper for handling xxx native binary
        /// </summary>
        public static class xxxInteropUtilities
        {
            /// <summary>
            /// Wrapper Class for NativeMethods to xxx native binary
            /// </summary>
            internal static class NativeMethods
            {
                [DllImport("xxxNativeBinary.dll")]
                public static extern int OpenHandle(
                    [Inuint clientVersion,
                    [InOutIntPtr reserved,
                    [Outout uint negotiatedVersion,
                    [Outout xxxSafeHandle clientHandle);
     
                [DllImport("xxxNativeBinary.dll")]
                public static extern int CloseHandle(
                    [InIntPtr clientHandle,
                    [InOutIntPtr reserved);
     
                [DllImport("xxxNativeBinary.dll")]
                public static extern void FreeMemory([InIntPtr memory);
     
                [DllImport("xxxNativeBinary.dll")]
                public static extern int DoSomethingNative(
                    [InxxxSafeHandle clientHandle,
                    [InMarshalAs(UnmanagedType.LPStruct)] Guid nativeGuid,
                    [InInt16 flags,
                    [InOutIntPtr reserved,
                    [Outout IntPtr nativeDataResult);
            }
     
            /// <summary>
            /// Additional struct and enum definitions for interfacing to xxx native binary go here
            /// </summary>
        }
        
        /// <summary>
        /// Class that provides a SafeHandle for the xxx native binary ClientHandle
        /// </summary>
        public sealed class xxxSafeHandle : SafeHandle
        {
            /// <summary>
            /// Class that provides a SafeHandle for the xxx native binary
            /// </summary>
            public xxxSafeHandle()
                : base(IntPtr.Zero, true)
            {
                return;
            }
     
            /// <summary>
            /// Returns a value to determine if internal IntPtr is still valid.
            /// </summary>
            public override bool IsInvalid
            {
                get
                {
                    return this.handle == IntPtr.Zero;
                }
            }
     
            /// <summary>
            /// Clean up the contained resource
            /// </summary>
            /// <returns>Success or Failure during CloseHandle</returns>
            protected override bool ReleaseHandle()
            {
                return xxxInteropUtilities.NativeMethods.CloseHandle(this.handle, IntPtr.Zero) == 0;
            }
        }
     
        /// <summary>
        /// Managed Class for xxxClient wrapping the NativeMethods for xxxNativeBinary.dll
        /// </summary>
        public class xxxClient : IDisposable
        {
            /// <summary>
            /// SafeHandle for managing NativeMethods wrapper for xxxNativeBinary.dll
            /// </summary>
            private xxxSafeHandle xxxHandle;
            
            /// <summary>
            /// Track whether Dispose has been called.
            /// </summary>
            private bool disposed = false;
            
            /// <summary>
            /// Gets the IntPtr for the xxxHandle to xxxNativeBinary.dll
            /// </summary>
            public xxxSafeHandle XxxHandle
            {
                get
                {
                    return this.xxxHandle;
                }
            }
            
            /// <summary>
            /// Constructor which sets up the xxxNativeBinary.dll NativeMethods
            /// </summary>
            public xxxClient()
            {
                this.xxxHandle = new xxxSafeHandle();
     
                uint clientVersion = 2;
                uint negotiatedVersion = 0;
                
                xxxInteropUtilities.NativeMethods.OpenHandle(clientVersion, IntPtr.Zero, out negotiatedVersion, out this.xxxHandle);
            }
     
            /// <summary> 
            /// Destructor which triggers the Dispose method 
            /// </summary> 
            ~xxxClient()
            {
                this.Dispose(false);
            }
     
            /// <summary> 
            /// Implement IDisposable. 
            /// Do not make this method virtual. 
            /// A derived class should not be able to override this method. 
            /// </summary> 
            public void Dispose()
            {
                this.Dispose(true);
     
                // This object will be cleaned up by the Dispose method. 
                // Therefore, you should call GC.SupressFinalize to 
                // take this object off the finalization queue 
                // and prevent finalization code for this object 
                // from executing a second time. 
                GC.SuppressFinalize(this);
            }
     
            /// <summary> 
            /// Dispose(bool disposing) executes in two distinct scenarios. 
            /// If disposing equals true, the method has been called directly 
            /// or indirectly by a user's code. Managed and unmanaged resources 
            /// can be disposed. 
            /// If disposing equals false, the method has been called by the 
            /// runtime from inside the finalizer and you should not reference 
            /// other objects. Only unmanaged resources can be disposed. 
            /// </summary> 
            /// <param name="disposing">Determines the phase of Dispose to run.</param> 
            protected virtual void Dispose(bool disposing)
            {
                if (!this.disposed)
                {
                    // If disposing equals true, dispose all managed 
                    // and unmanaged resources. 
                    if (disposing)
                    {
                        // Dispose managed types                     
                        this.xxxHandle.Dispose();
                    }
     
                    // Call the appropriate methods to clean up 
                    // unmanaged resources here. 
                    // If disposing is false, 
                    // only the following code is executed.
     
                    // Note disposing has been done. 
                    this.disposed = true;
                }
            }
     
            /// <summary>
            /// Example Method which Does Something Native
            /// </summary>
            /// <returns>The native return value</returns>
            public int DoSomethingNative()
            {
                int nativeResult = -1;
                IntPtr nativeMemory;
     
                int cmdSuccess = xxxInteropUtilities.NativeMethods.DoSomethingNative(this.xxxHandle, new Guid("Example Native Method Guid"), 0, IntPtr.Zero, out nativeMemory);
                if (cmdSuccess != 0)
                {
                    throw new Exception(cmdSuccess.ToString());
                }
     
                try
                {
                    //do something extra in managed land with the native data residing in nativeMemory...
                }
                finally
                {
                    //always wrap your access to the nativeMemory in a try/finally so that you *always* clean-up the native memory before exiting.
                    xxxInteropUtilities.NativeMethods.FreeMemory(nativeMemory);
                }
     
                return nativeResult;
            }
        }
    }
    
    Tuesday, March 13, 2012 6:05 PM
    Moderator
  • Thank you very much
    Tuesday, March 13, 2012 8:16 PM