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; } }