您的位置:首页 > 编程语言 > C语言/C++

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

2014-04-28 14:23 253 查看
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;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: