精华内容
下载资源
问答
  • C# 调用C++回调函数
    千次阅读
    2017-07-20 09:16:10

    转载自:http://www.cnblogs.com/dipwater/archive/2012/11/07/dipwater_delegate.html

    C# 调用C++回调函数过程如下:

    1. 定义回调函数对应的委托

    1 [UnmanagedFunctionPointerAttribute(CallingConvention.StdCall, CharSet = CharSet.Ansi)]
    2 public delegate void RealCallback(int hRealHandle, int dwDataType, IntPtr buffer, uint dwSize, IntPtr lpVoid);

      2. 参数定义为 Delegate,DllImport可参考http://blog.csdn.net/sibaison/article/details/70194273

    1 [DllImport(DvxSdkPath, EntryPoint = "DVR_StartRealPlay", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
    2 public static extern int StartRealPlay(int hUserHandle, Delegate callback);

      3. 创建一个委托的实例

    1 private RealCallback realCallBack = null;

      4. 定义委托对应的函数

    1 private void RealCallbackFun(int hRealHandle, int dwDataType, IntPtr lpReal, uint dwSize, IntPtr lpVoid)
    2 {
    3       
    4 }

      5. 给委托赋值

    1 realCallBack = RealCallbackFun;

      6. 使用委托

    1 StartRealPlay(handle, realCallBack);


    更多相关内容
  • 一个Demo,描述了C#如何在C++中注册函数并回调
  • c#调用C++动态库、执行回调函数,并回传结构体参数数据。vs2017环境编写C#C++动态库,这个为完整工程例子,可供相关人员学习参考。
  • C++回调C#

    2019-11-07 15:23:52
    现在比较流行C#C++融合:C#做GUI,开发效率高,C++做运算,运行效率高,二者兼得。 但是C++C#必然存在数据交互,C#C++dll的数据交互从来都是一个让人头疼的问题。 从调用方式看也有两种情况: 1、C#调用C++...

    现在比较流行C#与C++融合:C#做GUI,开发效率高,C++做运算,运行效率高,二者兼得。但是C++与C#必然存在数据交互,C#与C++dll的数据交互从来都是一个让人头疼的问题。

    从调用方式看也有两种情况:

    1、C#调用C++函数

    这种情况用的比较多,数据流向可以是C#流向C++,通过参数将数据传递给C++(如:SetData(double[] data));也可以是C++流向C#(如:GetData(double[] data))。

    2、C++ Callback

    这种情况是C++中通过Callback的方式调用C#代码,类似于C++做过一些处理后向C#发送事件,事件可以携带数据(如处理后的数据)。则C++中定义函数指针的方式是:

    typedef  void(*Render)(double* data, BOOL* color);

     

    C#作为委托,定义的函数被C++ callback:

    public delegate void RenderCallback([MarshalAs(UnmanagedType.LPArray, SizeConst =23)]double[] data, [MarshalAs(UnmanagedType.LPArray, SizeConst = 23)]int[] colors);

    千万注意,delegate中的double[]数组一定要加上MarshalAs标记,标记为传递数组,而且必须指定传递的数量,如果不标记数量,则每次只传递一个数值,这个问题折磨我很久才搞定!

    其他注意事项


    1、如何在C#中保持C++的函数指针

    回调函数的另一个注意事项是向C++ dll传递回调函数指针的问题

    假设有个函数向C++dll传递指针:

    public delegate void EKFRenderCallback(string data, string colors);

    public class EKFLib
    {
        [DllImport("EKFLib.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
        public static extern void SetRenderCallback(EKFRenderCallback render);

    }

    C#中如下传递被回调的函数:

    public void RenderCallback(string data, string color)
    {
        // rendering
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        EKFLib.SetRenderCallback(RenderCallback);
        EKFLib.Init();
    }

    这虽然没什么问题,但是通过SetRenderCallback()传入到C++的指针不受托管代码管理,在C#中认为此指针对象未被任何代码引用,GC做垃圾回收时,将会把C#本地的空指针回收,导致C++无法执行回调,出现“CallbackOnCollectedDelegate”错误:

    对“MotionCapture!MotionCapture.EKFRenderCallback::Invoke”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们。

    微软官网的例子是控制GC回收机制,这是个比较笨拙的方法,更加理所当然的方法是把委托定义成一个属性,指向一个new出来的callback,然后再把这个callback传递进C++dll中,这样,在C#端有对象引用,保证了GC不会回收此callback:

    public void RenderCallback(string data, string color)
    {
        // rendering
    }

    private EKFRenderCallback render;
    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        render = new EKFRenderCallback(RenderCallback);
        EKFLib.SetRenderCallback(render);
        EKFLib.Init();
    }


    2、__stdcall与_cdecl传递数据

    最近一个项目是通过C++ 的 dll做高速运算,然后把结果数据通过Callback的方式回调给C#(界面部分),结果总是在C#中接到回调事件后就直接挂掉(程序直接在毫无提示的情况下退出,没有任何调试信息或者提示)。

    导致问题的原因是,默认情况下,C++中如下定义的函数指针,默认是以_cdecl方式调用的:

    typedef  void(*Render)(double* data, BOOL* color);

    这种情况下,参数堆栈是由调用者(C++一侧)维护的,在C++调用此回调函数后,会把参数弹出堆栈而释放,导致C#读取数据时出现莫名其妙的错误。

    以上是回调函数传递数组可能出现的情况,而如下所示,只传递一个参数的情况,甚至会在C#方莫名其妙的卡死:

    typedef void (*CalibrationProgressCallback)(double percent);

    改为__stdcall的方式即可解决问题,申明如下:

    typedef  void(__stdcall *Render)(double* data, BOOL* color);

    以下来自网络的一段_cdecl和__stdcall的解释,必须牢记:

    1. __cdecl

    即所谓的C调用规则,按从右至左的顺序压参数入栈,由调用者把参数弹出栈。切记:对于传送参数的内存栈是由调用者来维护的。返回值在EAX中。因此,对于象printf这样变参数的函数必须用这种规则。编译器在编译的时候对这种调用规则的函数生成修饰名的饿时候,仅在输出函数名前加上一个下划线前缀,格式为_functionname。
    2. __stdcall

    按从右至左的顺序压参数入栈,由被调用者把参数弹出栈。_stdcall是Pascal程序的缺省调用方式,通常用于Win32 Api中,切记:函数自己在退出时清空堆栈,返回值在EAX中。  __stdcall调用约定在输出函数名前加上一个下划线前缀,后面加上一个“@”符号和其参数的字节数,格式为_functionname@number。如函数int func(int a, double b)的修饰名是_func@12

    所以,从C++ dll中回调函数给C#传递数据,必须由C#函数在使用完数据后(退出函数时)自己清空堆栈!所C++中的回调函数指针应该如下定义:

    typedef void (_stdcall *CalibrationProgressCallback)(double percent);

    总结:

    C++通过callback向C#传递数据必须注意以下几点:

    1、C++中的回调函数必须用_stdcall标记,使用stdcall方式回调;

    2、如果是数组,必须用 [MarshalAs(UnmanagedType.LPArray, SizeConst = 23)]标记参数,指定为数组且标记数组长度;

    3、C#方必须申明一个变量,用来指向C++的回调指针函数,避免被C#回收掉。

    展开全文
  • C#委托与C++回调函数处理

    热门讨论 2010-01-30 23:24:50
    告诉你怎么用C#委托处理dll中的回调函数。有几篇文档在里面
  • c++回调c#方法

    2013-10-17 14:28:56
    c++回调c#方法,传递结构体(中含结构体)
  • C#调用C++的dll实例,回调函数,string和int数组参数传递,在vs2010下调试通过,总结在这里,供大家参考。
  • 主要介绍了C#中异步回调函数用法,实例分析了异步回调函数的定义及使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
  • C#C++回调交互

    千次阅读 2017-11-14 14:18:54
    先总结一部分 using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; using UnityEngine;...public class InstructionDLL ... * C/C++ * typedef void (*D...

    先总结一部分

    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。
    
    

     

     

     

     

     

     

     

    展开全文
  • 附件是一套C#调用C++dll时,实现回调函数的Demo程序。亲测可用。
  • 直接上代码,注意SizeParaIndex的使用, 其代表回调函数传入参数数组长度在当前回调函数中的参数顺序,若此参数设置不正确会导致无法正确解析数组长度,直接影响用户定义回调函数实现。 //回调函数定义 ...

    直接上代码,注意SizeParamIndex的使用, 其代表回调函数传入参数数组长度在当前回调函数中的参数顺序,若此参数设置不正确会导致无法正确解析数组长度,直接影响用户定义回调函数实现。

    [StructLayout(LayoutKind.Sequential, Pack = 8)]
    public struct DIStatus
    {
        public int channel;//通道
        public int value;//当前值
    }
    
    [StructLayout(LayoutKind.Sequential, Pack = 8)]
    public struct DOStatus
    {
        public int channel;//通道
        public int value;//当前值
    }
            
    //回调函数定义
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void FnDiDoMonitor([MarshalAs(UnmanagedType.LPArray, SizeParamIndex =1 )]DIStatus[] diItems, UIntPtr diCnt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex =3)]DOStatus[] doItems, UIntPtr doCnt, IntPtr userParam);
    
    //回调函数实现
    public void DIDOMonitor(PLCControl.DIStatus[] diStatus, UIntPtr diCnt, PLCControl.DOStatus[] doStatus, UIntPtr doCnt, IntPtr userParam)
    {
        System.Diagnostics.Debug.WriteLine(diStatus.Length);
    }
    
    #if DEBUG
        [DllImport("PLCControlD.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
    #else
        [DllImport("PLCControl.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
    #endif
    public static extern bool PLC_AddDIDOMonitor([MarshalAs(UnmanagedType.FunctionPtr)]FnDiDoMonitor fn, IntPtr userParam);
    

    c++调用示例

    bool __stdcall PLC_AddDIDOMonitor(FNDIDOMONITOR fn, void* userParam)
    {
        if (nullptr == g_pPLC) return false;
    
        DIStatus itemDIs[3];
        ZeroMemory(itemDIs, sizeof(itemDIs));
        for (int i = 0; i < 3; ++i) {
            itemDIs[i].channel = i + 1;
            itemDIs[i].value = 3 + i;
        }
    
        DOStatus itemDOs[4];
        ZeroMemory(itemDOs, sizeof(itemDOs));
        for (int i = 0; i < 4; ++i) {
            itemDOs[i].channel = i + 1;
            itemDOs[i].value = 3 + i;
        }
    
        fn(itemDIs, 3, itemDOs, 4, nullptr);
    
        return true;
    }
    
    展开全文
  • 主要介绍了C++回调函数(CallBack)的用法,较为详细的分析了C++回调函数(CallBack)的原理并以实例形式总结了其具体用法,具有一定参考借鉴价值,需要的朋友可以参考下
  • 【背景】 C#(界面)调用C++实现的动态库时,C++在处理过程会有一些日志信息...1、回调函数指针定义 typedef void(*LogCallBack)(const char* msg); extern LogCallBack callBackFunc; typedef void(*ProcessCal...
  • C++调用C#注册的回调函数

    千次阅读 2017-12-28 19:12:01
    本文主要讲解C#注册回调函数提供给C++调用,用于异步通知机制。这在编程过程中是经常需要用到的模式。 此过程需要创建三个工程: 1. C++动态库工程 2. C++ CLR 托管动态库工程 3. C# 测试工程 接着前文C++封装...
  • C# Csharp 调用 C++的DLL中的回调函数

    热门讨论 2014-03-21 13:50:40
    一个是C++的DLL以及源码 一个是调用他的C#源码 都是VS2010编译测试通过
  • VS2017环境中,C#程序动态调用C++库中函数,并触发调用自身定义的回调函数
  • 1、普通函数调用 2、dll内子线程回调函数 3、借助OpenCV将dll图片显示到c#句柄(暂未实现 参照https://blog.csdn.net/u012250337/article/details/51601905)
  • 使用C++封装的VLC播放库dll,可供C#直接调用,可设置媒体状态的回调函数,使用十分简单
  • C++ librarylibrary.h#ifndef __LIBRARY_H__#define __LIBRARY_H__//exports.def#ifdef __cplusplus //__cplusplus是cpp中自定义的一个宏extern "C" { //告诉编译器,这部分代码按C语言的格式进行编译,而不是C++的#...
  • C#对接C++回调函数返回IntPtr事件信息转成结构体时出错,指定结构必须能直接复制到本机结构中,或是具有布局信息。 private int RealLoadPicCallback(IntPtr lAnalyzerHandle, uint dwEventType, IntPtr ...
  • C# 调用C/C++回调函数

    千次阅读 2015-08-22 00:17:10
    C/C++回调函数一般通过传递函数指针来实现,函数指针在C#中对应的就是委托.   Cpp代码  // 传入函数指针  typedef void (*FUNC)(int,char*);  JNAAPI bool processCallback(int a,FUNC...
  • C# 回调 C++ dll 函数

    2020-08-10 16:06:30
    //c++ 一个简单回调函数(导出函数) typedef void (WINAPI *StatusChangeFun)(int status); StatusChangeFun statusChanged; void WINAPI init(StatusChangeFun fun) { statusChanged = fun; //设置回调函数 } /...
  • 但如果c++ dll中有一些实时数据需要传递出来,那么一种常规做法就是在c++中设置回调函数,相当于提供一个接口,c#前端就可以利用这个接口来实时获取c++ dll中的数据 如下是一个实例: 首先定义c++ dll,用于模型...
  • C#调用C++函数时,如果C++函数需要传入回调函数,当C#调用时,如果直接传入函数作为参数的话,那么Release版本运行时就会出现**System.NullReferenceException: 未将对象引用设置到对象的实例。**这个异常问题。...
  • Unity使用的C++动态库回调C#函数

    千次阅读 2021-12-29 20:07:13
    Unity使用的C++动态库回调C#函数引言C++C#参考链接 引言 之前分享了一个文章:Unity显示C++动态库中的Log,其中使用到的主要能力就是,由C++动态库回调C#函数达到的。 这里我再对该功能进行专门的记录,并使用上面的...
  • 本文讲述了在C++项目中,怎么让C++调用C#的DLL动态链接库文件。 具体的实现步骤如下: 一、创建C# DLL,需要指定应用类型为“类库”,代码: namespace CSLib { public class Class1 { private string name; ...
  • c#调用c++带有回调函数方法的实现

    万次阅读 2012-11-06 16:41:49
    c++中有个回调函数指针的概念,只需要某个函数在调用定时器函数时传入一个函数指针就能达到目的,但C#中没有函数指针的概念,我们该怎样来实现呢。 其实说到回调函数,大家应该能想到c#中的委托,虽然名字不一样...
  • C#调Qt C++封装的dll以及C++回调 最近这几天一直在研究用C++封装成dll然后在winform里调用,包括调用C++里的回调函数,记录一下,学习的过程 我这个工程是用Qt C++封装一个往Linux上传文件的dll,然后在winform里...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 20,515
精华内容 8,206
关键字:

c# c++ 回调

c++ 订阅
c# 订阅
友情链接: MD5Sample.zip