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

时间:2022-03-14 02:27:00

C++的回调函数中有一个参数是,是返回一个字符串,原则如下: 
typedef   void   (*TDataEvent)(char   *AData   ,int   ALen); 
其中char   *AData是从DLL中返回一个字符串,串的内存已经在DLL中分配了 

下面中我在C#中定义的委托 
public   delegate   void   TDataEvent(Byte[]   AData,   int   ALen); 

下面是回调函数的设置代码: 
Event   =   new   clReceivelDllPoxy.TDataEvent(getDate); 
ReceDllPoxy.AddServer(1024,   Event,   2); 
其中   Event是上面委托的实例,我定义成一个成员这样就不会被自己释放 

下面是C#中回调函数的实现 
public   void   getDate(byte[]   AData,   int   ALen) 

//发现每次回调是   AData只有一个字节 

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Reflection.Emit;

namespace AppDllTest
{
    /// <summary>
    /// 非托管动态调用基类,基类不能直接使用,需要实现 FunTable()的虚函数
    /// </summary>
    public abstract class clDllBasePoxy
    {
        //-装入DLL---------
        public bool Open(string dllFileName)
        {
            Hand = LoadLibrary(dllFileName);
            if (Hand == 0)
            {
                return false;
            }

            FunSet(GetFunTable());
            return true;
        }  
        //-关闭DLL---
        public bool Close()
        {
            return FreeLibrary(Hand)!=0;
        }
        public abstract string[] GetFunTable(); //函数对应表由外部代理类通过 GetFunTable来设置

        #region //调用Windows32下的Kernele32库中的装入函数来完成对非托管DLL的引用-------
        //--------------------------------------------------------------
        [DllImport("Kernel32")]
        private static extern int GetProcAddress(int handle, String funcname);
        [DllImport("Kernel32")]
        private static extern int LoadLibrary(String funcname);
        [DllImport("Kernel32")]
        private static extern int FreeLibrary(int handle);
        private int Hand = 0; //DLL的句柄
        private static Delegate GetAddress(int dllModule, string functionname, Type t) //把指针转变成C#的代理
        {
            int addr = GetProcAddress(dllModule, functionname);
            if (addr == 0)
            {
                return null;
            }
            else
            {
                return Marshal.GetDelegateForFunctionPointer(new IntPtr(addr), t);
            }
        }
        //--关联代理和DLL中的函数-----------
        private bool FunSet(string[] aFun)
        {
            Type tp = this.GetType();
            string[] Value;
            for (int i = 0; i < aFun.Length; i++)
            {
                Value = aFun[i].Split(','); //"Box, TBox, _Box" 第一项是代理的实例名,第二项是代理的定义名,第三项是DLL中的函数名
                if (Value.Length == 3)
                {
                    FieldInfo fi = tp.GetField(Value[0].Trim());  //找实例
                    Type type = tp.GetNestedType(Value[1].Trim());//找尾托
                    if (fi != null && type != null)
                    {
                        fi.SetValue(this, GetAddress(Hand, Value[2].Trim(), type)); //创建关联
                    }
                }
            }
            return true;
        } 
        #endregion
    }

    public class clDllPoxy : clDllBasePoxy
    {
        public override string[] GetFunTable()
        {
            string[] FunTable = new string[]{
            "GetFixParamCount, TGetFixParamCount, _GetFixParamCount",
            "GetFixParam, TGetFixParam, _GetFixParam"
            };
            return FunTable;
        }

        //--输出函数----------------------------------------------
        public TGetFixParamCount GetFixParamCount;
        public TGetFixParam GetFixParam;
        //--代理描述----------------------------------------------
        public delegate int TGetFixParamCount();                     //获取固定参数个数
        public delegate bool TGetFixParam(int AIndex, byte []AOutBuf); //固定参数
    }



    /// <summary>
    /// C#动态调用托管DLL的基类--------------
    /// </summary>
    public class clNetDllPoxy
    {
        //--装入动态库----------
        public bool Open(string dllFileName, string className)
        {
            FAsembly = Assembly.LoadFrom(dllFileName);
            if (FAsembly == null)
            {
                return false;
            }
            
            Type type = FAsembly.GetTypes()[0]; //第一个对应的名字空间当成是调用的名字空间
            FDllName = dllFileName;
            FClassName = className;
            if (type != null)
            {
                FNameSpace = type.Namespace;
            }
            return true;
        }

        //--设置Dll中的函数范围---------
        public void SetArea(string nameSpace, string className)
        {
            FNameSpace = nameSpace;
            FClassName = className;
        }
        //--调用指定的方法,注:方法的所有参数都转化成对象类型
        public object Invoke(string funName, object[] ObjArray_Parameter)
        {
            try
            {
                Type[] types = FAsembly.GetTypes();
                foreach (Type tp in types)
                {
                    if (tp.Namespace == FNameSpace && tp.Name == FClassName)
                    {
                        MethodInfo metInfo = tp.GetMethod(funName);
                        if (metInfo != null)
                        {
                            object obj = Activator.CreateInstance(tp); //创建类对象
                            if (obj != null)
                            {
                                return metInfo.Invoke(obj, ObjArray_Parameter);
                            }
                        }
                    }
                }
            }
            catch
            { }
            return null;

        }
        
        private Assembly FAsembly; //Dll的程序集
        private string FDllName;
        private string FNameSpace;
        private string FClassName;
    }
    
}