C#与C++回调交互

来源:互联网 发布:淘宝店面怎么装修 编辑:程序博客网 时间:2024/05/16 17:17

先总结一部分


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)    {            }}[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。




原创粉丝点击