C#与C++回调交互

先总结一部分

using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;

public class InstructionDLL
{
    /*
     * C/C++
     * typedef void (*DPNewCallIn) (HANDLE hSession, DPMedia * pMedia);
     * typedef void (*DPSessionError) (HANDLE hSession, char * strError);
     * typedef void (*DPNewMessage) (char * msginfo, int rip);
     * typedef void (*DPRemoteHangUp) (HANDLE hSession);
     * 
     * 注册回调函数
     * extern "C" __declspec(dllexport) void RegistCallBackFunc(DPNewCallIn cbNewCallIn, DPSessionError cbSessionError,
                        					DPNewMessage cbNewMessage, DPRemoteHangUp cbRemoteHangUp);
     * 
     * 第一个回调方法参数里面的结构体定义:
     * typedef struct
     * {
     *     int nVideo;
     *     int nAudio;
     *     unsigned char Description[];
     * } DPMedia
     * 


     * C#关键代码:
     */
    //注册回调函数
    [DllImport("DPCall2.dll", CallingConvention = CallingConvention.StdCall)]
    public static extern void RegistCallBackFunc(NewCallInCallbackDelegate cbNewCallIn, 
                                                 CallErrorCallbackDelegate cbSessionError, 
                                                 CallNewMessageCallbackDelegate cbNewMessage, 
                                                 RemoteHangUpCallbackDelegate cbRemoteHangUp);

    //设置委托
    [UnmanagedFunctionPointerAttribute(CallingConvention.StdCall, CharSet = CharSet.Ansi)]
    public delegate void NewCallInCallbackDelegate(int hSession, ref DpMedia pMedia);

    [UnmanagedFunctionPointerAttribute(CallingConvention.StdCall, CharSet = CharSet.Ansi)]
    public delegate void CallErrorCallbackDelegate(int hSession, [MarshalAs(UnmanagedType.LPArray, SizeConst = 8000)]byte[] strError);

    [UnmanagedFunctionPointerAttribute(CallingConvention.StdCall, CharSet = CharSet.Ansi)]
    public delegate void CallNewMessageCallbackDelegate([MarshalAs(UnmanagedType.LPArray, SizeConst = 8000)]byte[] msg, int rip);

    [UnmanagedFunctionPointerAttribute(CallingConvention.StdCall, CharSet = CharSet.Ansi)]
    public delegate void RemoteHangUpCallbackDelegate(int hSession);

    public struct DataListener
    {
        public NewCallInCallbackDelegate OnNewCallInEvent;
        public CallErrorCallbackDelegate OnCallErrorEvent;
        public CallNewMessageCallbackDelegate OnCallNewMessageEvent;
        public RemoteHangUpCallbackDelegate OnRemoteHangUpEvent;

        public DataListener(NewCallInCallbackDelegate newCall,CallErrorCallbackDelegate callError,
                            CallNewMessageCallbackDelegate callNewMessage,RemoteHangUpCallbackDelegate remoteHang)
        {
            OnNewCallInEvent = newCall;
            OnCallErrorEvent = callError;
            OnCallNewMessageEvent = callNewMessage;
            OnRemoteHangUpEvent = remoteHang;
        }
    }

    /*
     * 第二种为直接调用Dll文件,放入Plugins下
     * 
     * [DllImport("CSharpUseCDLL")]
     * private static extern void fun0(ref int a);   
     */
}

public class VisionListener
{
    InstructionDLL.DataListener dataListener;

    public void Init()
    {
        dataListener = new InstructionDLL.DataListener(NewCallInCallbackDelegate, CallErrorCallbackDelegate, CallNewMessageCallbackDelegate, RemoteHangUpCallbackDelegate);
    }

    void NewCallInCallbackDelegate(int hSession, ref DpMedia pMedia)
    {
        
    }

    void CallErrorCallbackDelegate(int hSession, byte[] strError)
    {
        
    }

    void CallNewMessageCallbackDelegate(byte[] msg, int rip)
    {
        
    }

    void RemoteHangUpCallbackDelegate(int hSession)
    {
        
    }

    void OnReceiveData(int id, int size, IntPtr data)
    {
        if (id == 2001)
        {
            try
            {
                Hand_Info pointer = (Hand_Info)Marshal.PtrToStructure(data, typeof(Hand_Info));
                GeeVisionData.Enqueue(pointer);
            }
            catch (Exception e)
            {
                Debug.Log(e.Message);
            }
        }
    }

   [StructLayout(LayoutKind.Sequential)]
    public struct Hand_Info
    {
        public int Gesture_ID; //!< static  gesture event ID
        public int Gesturedy_ID; //!< dynamic gesture event ID

        public int Obeject_ID;
        public Vector3 Center3D;
        public Vector2 Center2D;
    }
}

[StructLayout(LayoutKind.Sequential)]
public struct DpMedia
{
    public int nVideo;
    public int nAudio;
    [MarshalAs(UnmanagedType.LPArray, SizeConst = 4)]
    public byte[] Description;
}
					  

 1. 不返回值的参数 C++ 原型: 
 * bool SendNewSms(char *szTel, char *szMessage); 
 * C#引用; 
 * [DllImport( "CdmaCard.dll",EntryPoint="SendNewSms")] 
 * public static extern bool SendNewSms(string phone,string msg); 
  
 * 2. 带返回值(char *) C++原型: 
 * BOOL GetCardErrorMessage(char *szErrorMessage , int errorCode); C#引用 
 * [DllImport( "CdmaCard.dll",EntryPoint="GetCardErrorMessage")]     
 * public static extern int GetCardErrorMessage(StringBuilder msg,int errorCode); 
 * StringBuilder buf = new StringBuilder(1024);//指定的Buf大小必须大于可能的最大长度        
 * GetCardErrorMessage(buf,1); 
  
 * 3. 带返回值(其他类型) C++原型:   
 * BOOL GetSmsSaveStation (int *nSmsStation); C#引用   
 * [DllImport( "CdmaCard.dll",EntryPoint="GetSmsSaveStation")]     
 * public static extern bool GetSmsSaveStation(ref int nStation); 
  
 * 4. 传递结构体指针(C++填充) C++原型: 
 * struct NET_INFO_STRUCT 
 * {   
 *    DWORD nDurationTime; //持续时间     double nReceiveByte; //接收字节    double nSendByte;   //发送字节 
 * };   
 * BOOL NetGetConnectDetail(NET_INFO_STRUCT *lpNetInfo); C#引用    
 * public struct NET_INFO_STRUCT 
 * {   
 *    public uint nDurationTime; //持续时间
 *    public double nReceiveByte; //接收字节    
 *    public double nSendByte;   //发送字节 
 * } 

 * [DllImport( "CdmaCard.dll",EntryPoint="NetGetConnectDetail")]          
 * public static extern int NetGetConnectDetail(ref NET_INFO_STRUCT pNetInfo);                  
 * NET_INFO_STRUCT netInfo = new NET_INFO_STRUCT();          
 * NetGetConnectDetail(ref netInfo);           

 * 5. 传递结构体数组(C++来填充) C++原型: 
 * struct UIM_BOOK_STRUCT 
 * {   
 *    int UimIndex;    
 *    char szName[15];    
 *    char szPhone[21]; 
 * }; 

 * int ReadUimAllBook(UIM_BOOK_STRUCT lpUimBookItem[],int nMaxArraySize); C#引用 

 * [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]//可以指定编码类型 
 * public struct UIM_BOOK_STRUCT 
 * {   
 *    public int UimIndex;    
 *    [MarshalAs(UnmanagedType.ByValTStr, SizeConst= 15)]    
 *    public string szName;    
 *    [MarshalAs(UnmanagedType.ByValTStr, SizeConst= 21)]    
 *    public string szPhone; 
 * }; 

 * [DllImport( "CdmaCard.dll",EntryPoint="ReadUimAllBook")] 
 * public static extern int ReadUimAllBook([Out] UIM_BOOK_STRUCT [] lpUimBookItem,int nMaxArraySize); 
 * UIM_BOOK_STRUCT[] p = new UIM_BOOK_STRUCT[20]; int ret = ReadUimAllBook(p,p.Length);
 * 
 * 6. 注意问题
 * 类型不一致,会导致调用失败, 
 * (1) long 类型,在C++中是4字节的整数,在C#中是8字节的整数;
 * (2) 字符串类型的设置不正确;    以下是几个简单的window调用    
 * 
 * [System.Security.SuppressUnmanagedCodeSecurity] // We won't use this maliciously         
 * [DllImport("User32.dll", CharSet=CharSet.Auto)]          
 * public static extern bool ScreenToClient(IntPtr hWnd, ref System.Drawing.Point rect);   
 * 
 * [System.Security.SuppressUnmanagedCodeSecurity] // We won't use this maliciously          
 * [DllImport("User32.dll", CharSet=CharSet.Auto)]         
 * public static extern bool GetWindowRect(IntPtr hWnd, out System.Drawing.Rectangle rect);    
 * 
 * [System.Security.SuppressUnmanagedCodeSecurity] // We won't use this maliciously          
 * [DllImport("User32.dll", CharSet=CharSet.Auto)]          
 * public static extern bool UnregisterClass([MarshalAs(UnmanagedType.LPTStr)] string className, IntPtr instanceHandle);
 
 
 * 1. 如果函数只有传入参数,比如: C/C++ Code   C++中的输出函数  
 * int __declspec(dllexport) test(const int N) 
 * {  
 *    return N+10; 
 * }
 * 
 * 对应的C#代码为:  C# Code   
 * [DllImport("test.dll", EntryPoint = "#1")] 
 * public static extern int test(int m);
 * 
 * private void button1_Click(object sender, EventArgs e) 
 * {  
 *    textBox1.Text= test(10).ToString(); 
 * }
 * 
 * 
 * 2. 如果函数有传出参数,比如:  C/C++ Code  C++  
 * void __declspec(dllexport) test(const int N, int& Z) 
 * { 
 *    Z=N+10; 
 * }  
 * 
 * 对应的C#代码:  C# Code  
 * [DllImport("test.dll", EntryPoint = "#1")]  
 * public static extern double test(int m, ref int n); 
 * private void button1_Click(object sender, EventArgs e) 
 * {  
 *    int N = 0;  
 *    test1(10, ref N); 
 *    textBox1.Text= N.ToString();
 * } 
 * 
 * 
 * 3. 带传入数组:  C/C++ Code   
 * void __declspec(dllexport) test(const int N, const int n[], int& Z) 
 * {  
 *    for (int i=0; i<N; i++) 
 *    {  
 *       Z+=n[i]; 
 *    } 
 * }  
 * 
 * C#代码:  C# Code
 * [DllImport("test.dll", EntryPoint = "#1")] 
 * public static extern double test(int N, int[] n, ref int Z); 
 * private void button1_Click(object sender, EventArgs e) 
 * {  
 *    int N = 0; 
 *    int[] n;  
 *    n = new int[10];   
 *    for (int i = 0; i < 10; i++) 
 *    {  
 *       n[i] = i
 *    }  
 *    test(n.Length, n, ref N); 
 *    textBox1.Text= N.ToString(); 
 * } 
 * 
 * 
 * 4. 带传出数组:  C++不能直接传出数组,只传出数组指针,  C/C++ Code   
 * void __declspec(dllexport) test(const int M, const int n[], int *N) 
 * {  
 *    for (int i=0; i<M; i++) 
 *    {  
 *       N[i]=n[i]+10; 
 *    } 
 * }  
 * 
 * 对应的C#代码:  C# Code   
 * [DllImport("test.dll", EntryPoint = "#1")]  
 * public static extern void test(int N, int[] n, [MarshalAs(UnmanagedTyp e.LPArray,SizeParamIndex=1)] int[] Z); 
 * private void button1_Click(object sender, EventArgs e) 
 * {  
 *    int N = 1000; 
 *    int[] n, Z;  
 *    n = new int[N];Z = new int[N]; 
 *    for (int i = 0; i < N; i++) 
 *    {
 *       n[i] = i
 *    }  
 *    test(n.Length, n, Z);  
 *    for (int i=0; i<Z.Length; i++) 
 *    {  
 *       textBox1.AppendText(Z[i].ToString()+"n"); 
 *    } 
 * }  
 * 
 * 这里声明函数入口时,注意这 句 [MarshalAs(UnmanagedType.LPArray,SizeParamIndex=1)] int[] Z  
 * 在C#中数组是直接使用的,而在C++中返回的是数组的指针,这句用来转化这两种不同的类型.
 * 
 * 
 * 5. 传出字符数组: C++定义:  C/C++ Code   
 * void __declspec(dllexport) test(int i, double &a, double &b, char t [5])    
 * 
 * C#对应声明:  C# Code  
 * [DllImport("dll.dll", EntryPoint = "test")]    
 * public static extern void test(int i, ref double a, ref double b, [Ou t, MarshalAs(UnmanagedType.LPArray)] char[] t);   
 * char[] t = new char[5];   
 * test(i, ref a, ref b, t); 
 * 
 * 字符数组的传递基本与4相似,只是mashalAs 时前面加上Out。

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值