• unity c #和c++ 通信


    流程

    通常情况下C++ 封装在so库,放在unity 工程里的Plugins文件夹里,需要设置对应的编译结构(32bit或者64bit), C# 通过DllImport调用C++接口
    • unsafe 指针
    • IntPtr 代替指针

    通信文件结构

    以sdk为例
    //命名空间
    namespace JOE
    {
      using System;
      using System.Runtime.InteropServices;
      public class JoeSdkWrapper : System.IDisposable
      {
         //so库的名称
         private const string SDKLib = "joe";
         //通用句柄
         private IntPtr handle = IntPtr.Zero;
        
         public JoeSdkWrapper() { }
         //供外部C#调用的接口,封装了c++映射接口
         public string GetVersion()
         {
              return sdk_api.GetVersion();
         }
      }
      //用struct 封装 所有的c++ 映射接口
      private struct sdk_api
      {
           /// <summary>
           /// Get version number of  SDK api
           /// </summary>
           /// <returns>version</returns>
           [DllImport(STHandLib)]
           public static extern string GetVersion();//名字必须和C++头文件的方法名一致
      }
    }

    通用接口映射

    • 必须映射重写部分
      1. struct
       //C++
       typedef struct JoeTime{
           float resizeTime;
     
           float joe_matrix[3][3];
       }HandTime;
         //C#
        [StructLayout(LayoutKind.Sequential)]
        public struct JoeTime
        {
           
            public float resizeTime;
     
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)]//特别注意这个一定要声明数组的size大小
            public float[] joe_matrix;           ///matrix [ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f ]
        }
      2. enum
       //C++
       typedef enum {
           DOWN= 0,
           UP = 1,
       } JoeType;
       //C#
       public enum JoeType
       {
           DOWN= 0,
           UP = 1,
           
       }
    3. function
       //C++
       const char* GetVersion();
       //C#
       [DllImport(SDKLib)]
       public static extern string GetVersion();//名字必须和C++头文件的方法名一致
    • 常见的类型映射总结 ,用到的时候可查询
    //c++:HANDLE(void   *)          ----    c#:System.IntPtr      
    //c++:Byte(unsigned   char)     ----    c#:System.Byte       
    //c++:SHORT(short)              ----    c#:System.Int16       
    //c++:WORD(unsigned   short)    ----    c#:System.UInt16      
    //c++:INT(int)                 ----    c#:System.Int16      
    //c++:INT(int)                  ----    c#:System.Int32       
    //c++:UINT(unsigned   int)      ----    c#:System.UInt16      
    //c++:UINT(unsigned   int)      ----    c#:System.UInt32      
    //c++:LONG(long)                ----    c#:System.Int32       
    //c++:ULONG(unsigned   long)    ----    c#:System.UInt32       
    //c++:DWORD(unsigned   long)    ----    c#:System.UInt32       
    //c++:DECIMAL                   ----    c#:System.Decimal       
    //c++:BOOL(long)                ----    c#:System.Boolean       
    //c++:CHAR(char)                ----    c#:System.Char       
    //c++:LPSTR(char   *)           ----    c#:System.String       
    //c++:LPWSTR(wchar_t   *)       ----    c#:System.String       
    //c++:LPCSTR(const   char   *)  ----    c#:System.String       
    //c++:LPCWSTR(const   wchar_t   *)      ----    c#:System.String       
    //c++:PCAHR(char   *)   ----    c#:System.String       
    //c++:BSTR              ----    c#:System.String       
    //c++:FLOAT(float)      ----    c#:System.Single       
    //c++:DOUBLE(double)    ----    c#:System.Double       
    //c++:VARIANT           ----    c#:System.Object       
    //c++:PBYTE(byte   *)   ----    c#:System.Byte[]       
    //c++:BSTR      ----    c#:StringBuilder      
    //c++:LPCTSTR   ----    c#:StringBuilder      
    //c++:LPCTSTR   ----    c#:string      
    //c++:LPTSTR    ----    c#:[MarshalAs(UnmanagedType.LPTStr)] string       
    //c++:LPTSTR 输出变量名    ----    c#:StringBuilder 输出变量名      
    //c++:LPCWSTR   ----    c#:IntPtr      
    //c++:BOOL      ----    c#:bool         
    //c++:HMODULE   ----    c#:IntPtr          
    //c++:HINSTANCE ----    c#:IntPtr       
    //c++:结构体    ----    c#:public struct 结构体{};       
    //c++:结构体 **变量名   ----    c#:out 变量名 
    //C#中提前申明一个结构体实例化后的变量名      
    //c++:结构体 &变量名    ----    c#:ref 结构体 变量名               
    //c++:WORD      ----    c#:ushort      
    //c++:DWORD     ----    c#:uint      
    //c++:DWORD     ----    c#:int      
    //c++:UCHAR     ----    c#:int      
    //c++:UCHAR     ----    c#:byte      
    //c++:UCHAR*    ----    c#:string      
    //c++:UCHAR*    ----    c#:IntPtr      
    //c++:GUID      ----    c#:Guid      
    //c++:Handle    ----    c#:IntPtr      
    //c++:HWND      ----    c#:IntPtr      
    //c++:DWORD     ----    c#:int      
    //c++:COLORREF  ----    c#:uint      
    //c++:unsigned char     ----    c#:byte      
    //c++:unsigned char *   ----    c#:ref byte      
    //c++:unsigned char *   ----    c#:[MarshalAs(UnmanagedType.LPArray)] byte[]      
    //c++:unsigned char *   ----    c#:[MarshalAs(UnmanagedType.LPArray)] IntPtr      
    //c++:unsigned char &   ----    c#:ref byte      
    //c++:unsigned char 变量名      ----    c#:byte 变量名      
    //c++:unsigned short 变量名     ----    c#:ushort 变量名      
    //c++:unsigned int 变量名       ----    c#:uint 变量名      
    //c++:unsigned long 变量名      ----    c#:ulong 变量名      
    //c++:char 变量名       ----    c#:byte 变量名 
    //C++中一个字符用一个字节表示,C#中一个字符用两个字节表示      
    //c++:char 数组名[数组大小]     ----    c#:MarshalAs(UnmanagedType.ByValTStr, SizeConst = 数组大小)]      
    public string 数组名; ushort      
    //c++:char *            ----    c#:string     
    //传入参数      
    //c++:char *            ----    c#:StringBuilder
    //传出参数      
    //c++:char *变量名      ----    c#:ref string 变量名      
    //c++:char *输入变量名  ----    c#:string 输入变量名      
    //c++:char *输出变量名  ----    c#:[MarshalAs(UnmanagedType.LPStr)] StringBuilder 输出变量名      
    //c++:char **           ----    c#:string      
    //c++:char **变量名     ----    c#:ref string 变量名      
    //c++:const char *      ----    c#:string      
    //c++:char[]            ----    c#:string      
    //c++:char 变量名[数组大小]     ----    c#:[MarshalAs(UnmanagedType.ByValTStr,SizeConst=数组大小)] public string 变量名;   
    //c++:struct 结构体名 *变量名   ----    c#:ref 结构体名 变量名      
    //c++:委托 变量名   ----    c#:委托 变量名      
    //c++:int       ----    c#:int      
    //c++:int       ----    c#:ref int      
    //c++:int &     ----    c#:ref int      
    //c++:int *     ----    c#:ref int    
    //C#中调用前需定义int 变量名 = 0;      
    //c++:*int      ----    c#:IntPtr      
    //c++:int32 PIPTR *     ----    c#:int32[]      
    //c++:float PIPTR *     ----    c#:float[]              
    //c++:double** 数组名          ----    c#:ref double 数组名      
    //c++:double*[] 数组名          ----    c#:ref double 数组名      
    //c++:long          ----    c#:int      
    //c++:ulong         ----    c#:int              
    //c++:UINT8 *       ----    c#:ref byte     
    //C#中调用前需定义byte 变量名 = new byte();              
    //c++:handle    ----    c#:IntPtr      
    //c++:hwnd      ----    c#:IntPtr                      
    //c++:void *    ----    c#:IntPtr              
    //c++:void * user_obj_param    ----    c#:IntPtr user_obj_param      
    //c++:void * 对象名称    ----    c#:([MarshalAs(UnmanagedType.AsAny)]Object 对象名称              
    //c++:char, INT8, SBYTE, CHAR                               ----    c#:System.SByte        
    //c++:short, short int, INT16, SHORT                        ----    c#:System.Int16        
    //c++:int, long, long int, INT32, LONG32, BOOL , INT        ----    c#:System.Int32        
    //c++:__int64, INT64, LONGLONG                              ----    c#:System.Int64        
    //c++:unsigned char, UINT8, UCHAR , BYTE                    ----    c#:System.Byte        
    //c++:unsigned short, UINT16, USHORT, WORD, ATOM, WCHAR , __wchar_t             ---- c#:System.UInt16        
    //c++:unsigned, unsigned int, UINT32, ULONG32, DWORD32, ULONG, DWORD, UINT      ----    c#:System.UInt32        
    //c++:unsigned __int64, UINT64, DWORDLONG, ULONGLONG                            ----    c#:System.UInt64        
    //c++:float, FLOAT                                                              ----    c#:System.Single        
    //c++:double, long double, DOUBLE                                               ----    c#:System.Double
    //双针指类型参数,可以用 ref IntPtr       

    调用接口

    • 调用接口的时候需要将struct 数据结构转成 IntPtr,具体写法如下:
       IntPtr ParamPtr = Marshal.AllocHGlobal(Marshal.SizeOf(IntrinsicParam));
       Marshal.StructureToPtr(IntrinsicParam, ParamPtr, true);
       //TODO :使用ParamPtr
       Marshal.FreeHGlobal(ParamPtr);
    • 将byte[] 转成IntPtr
       //colorData 是byte[],rgb.data是IntPtr
       rgb.data = Marshal.AllocHGlobal(colorData.Length);
       Marshal.Copy(colorData, 0, rgb.data, colorData.Length);
    • 将返回值是IntPtr 转回 struct
      //hans 是IntPtr ,HAPPY 是struct类型
      HAPPY handGesture = (HAPPY)Marshal.PtrToStructure(hands, typeof(HAPPY));
    • 将返回值是IntPtr 转回 byte[]
    /points_3d 是IntPtr ,KeyPointsPosArr,是byte[],KeyPointsCount * 3是byte[]的字节总数
      Marshal.Copy(points_3d, KeyPointsPosArr, 0, KeyPointsCount * 3);
    • 记得释放IntPtr
       Marshal.FreeHGlobal(one);

    特殊情况

    • struct 数组里的string数组赋值
      IntPtr[] model_files_array = new IntPtr[2];
      // Each IntPtr array element will point to a copy of a
      // string element in the openFileDialog.FileNames array.
      for (int i = 0; i < 2; i++)
      {
          model_files_array[i] = Marshal.StringToHGlobalAnsi(Path[i]);
      }
      // In order to obtain the address of the IntPtr array,
      // we must fix it in memory. We do this using GCHandle.
      GCHandle gch = GCHandle.Alloc(model_files_array, GCHandleType.Pinned);
      // pimage_files will point to the head of the IntPtr array.
      IntPtr filesFirstPtr = gch.AddrOfPinnedObject();
    • 将intprt转成结构体数组
    public static void MarshalUnmananagedArray2Struct<T>(IntPtr unmanagedArray, int length, out T[] mangagedArray)
    {
        var size = Marshal.SizeOf(typeof(T));
        mangagedArray = new T[length];
        for (int i = 0; i < length; i++)
        {
            IntPtr ins = new IntPtr(unmanagedArray.ToInt64() + i * size);
            mangagedArray[i] = Marshal.PtrToStructure<T>(ins);
        }
    }

    常见问题

    C++ long 是4字节,对应c#的int
    喜欢unity 和酷炫的效果。欢迎留言交流。
  • 相关阅读:
    01(b)无约束优化(准备知识)
    01(a)一元函数_多元函数_无约束极值问题的求解
    谱聚类
    分类算法
    Implementing EM for Gaussian mixtures
    0-1背包问题1
    ML_推荐系统与降维
    Machine Learning: Clustering & Retrieval机器学习之聚类和信息检索(框架)
    Linux命令
    Udacity_机器学习
  • 原文地址:https://www.cnblogs.com/smilejoi/p/14785439.html
Copyright © 2020-2023  润新知