当前位置:编程学习 > C#/ASP.NET >>

C++调用C#的回调函数问题

我在最近一个项目中遇到点问题,背景情况如下:
1.我有一个用VC6写的DLL,该DLL有一个引出函数,如下:
   void __stdcall InitCommMethod(SEND_FUNC funSend, RECV_FUNC funRecv);
该函数的两个参数定义如下:
   typedef int (*SEND_FUNC)(const char *data, int dtLen);
   typedef int (*RECV_FUNC)(char* data, int dtLen);、
该DLL实现的是一个加密协议模块,为了支持多种底层通信方式,如串口、USB、蓝牙等,该DLL并未实现具体的通信编码,仅引出了上述函数作为与通信层的接口。

2.项目要求使用C#来编程,使用了.net带的SerialPort控件来为上述DLL提供底层通信的具体实现。

遇到的问题描述如下:
1.我在C#中定义了一个代理类型,如下:
    public delegate int serialDelegate(IntPtr data, int size);
  接着,定义了两个如下变量,并实现了两个方法Send和Read;
     serialDelegate ptrSend;
     serialDelegate ptrRecv;
  最后,完成了如下初始化:
    ptrSend = new serialDelegate(this.Send);
    ptrRecv = new serialDelegate(this.Read);
    InitCommMethod(Marshal.GetFunctionPointerForDelegate(ptrSend), 
                   Marshal.GetFunctionPointerForDelegate(ptrRecv));
2.当我在使用VC6调试上述加密协议模块DLL时,遇到如下状况:
  —>在DLL中回调ptrSend方法时,程序正确;
  —>在DLL中回调ptrRecv方法时,能正确返回从串口接收到的数据;DLL中的调用链为:
         processReceivedData->receiveData->ptrRecv;
     调试发现只要在DLL中调用了ptrRecv函数,则一旦返回,必定报地址冲突错误。如果没有调用
     ptrRecv函数,则不会出现任何错误;
3.C#中的Read函数如下:
        public int Read(IntPtr data, int size)
        {
            byte[] rData = new byte[size];
            int temp = this.serialPort1.Read(rData, 0, size);
            Marshal.Copy(rData, 0, data, temp);
            //data = IntPtr.Zero;
            return temp;
        }

    在C#的Read函数中进一步调试后发现只要调用了Marshal.Copy方法,则VC6就必定会报错;至此错误定位在了
    Marshal.Copy上。我到现在也没有找到问题的解决办法。注意:Marshal.Copy能把接收到的数据正确的传入DLL中。


--------------------编程问答-------------------- 补充一下:
     DLL中的调用链为: 
        processReceivedData->receiveData->ptrRecv; 
    调试发现只要在DLL中调用了ptrRecv函数,则一旦processReceivedData函数返回,就会报错,而receiveData函数返回并不报错。
         int receiveData(char* pData, int iLen)
{
    return g_funRecv(pData, iLen);//g_funRecv=ptrRecv;
}

        int processReceivedData()
{
            //m_szData为全局数组;iPos为全局数组当前的写入位置;
    int iLen =RecvData(m_szData + iPos, sizeof(m_szData) - iPos);
            return iLen;        
        } --------------------编程问答-------------------- 我初步判断错误原因是:C#托管内存管理器释放了函数传入的非托管内存,从而导致了dll内部内存地址访问冲突。怎么解决这个问题呢?
--------------------编程问答--------------------     /// <summary>
        /// 启动TCP服务 
        /// </summary>
        /// <param name="outTime">读取数据超时</param>
        /// <param name="sendTime">处理数据超时</param>
        /// <param name="port">开启的TCP端口</param>
        /// <param name="dealFunc">函数委托,回调</param>
        /// <returns>True 表示成功 False表示失败</returns>
        [DllImport(DLLName, CharSet = CharSet.Ansi)]
        public static extern Boolean RunServer(int outTime, int sendTime, int port, [MarshalAs(UnmanagedType.FunctionPtr)] dlBussPack485 dealFunc);

给你一个样本,DELPHHI的回调方式,注意前面的调用Marshal方式. --------------------编程问答-------------------- 楼主的回调函数都没有实现,而且定义的参数都不正确当然有问题了。

public delegate int serialDelegate(byte[] data, int size); 
--------------------编程问答-------------------- C#内的data地址和C++内的data地址不一致? --------------------编程问答-------------------- 感谢大家对这一问题的关注。我的问题在于:c#编写的函数传入DLL后,在DLL中回调c#函数,并且
传入在DLL中分配了内存的数组参数。调用成功后,过一段时间DLL中的代码报出地址访问冲突。
我查了DLL中的代码,可以肯定代码不会错误。我想应该是C#使用的公共运行时环境对在DLL中
分配内存后传入C#函数的参数进行了非法释放导致了DLL内部内存被破坏了。
补充:.NET技术 ,  C#
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,