如题,
[DllImport("dllfile.dll")]//这里"dllfile.dll"只能用常量表示
public static extern void ShowMessage(string Msg);
有没有其它方法可以动态调用Dll啊?
[DllImport("dllfile.dll")]//这里"dllfile.dll"只能用常量表示
public static extern void ShowMessage(string Msg);
有没有其它方法可以动态调用Dll啊?
托管代码的参数用loadlibrary找到函数入口点,再用从托管代码传来的参数
调用dll中的函数。
虽然绕了个弯,但应该可行
C# 支持调用C 的函数指针
不过要用 委托代替。loadlibrary C#里没用过 ,不过给你一个 类似的调用函数指针的列子。
//声明一个委托 public delegate IntPtr NewWndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); //把最后一个参数生命为 委托
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, NewWndProc wndproc);//实列化委托(这里就是回调函数) wpr= new NewWndProc(this.TextBoxWndProc); //替换控件的默认处理函数(并且返回原始的 默认处理函数,是一个函数指针的地质) oldWndProc=SetWindowLong(textBox1.Handle,GWL_WNDPROC,wpr);------------------------------------------------------------
http://blog.csdn.net/flashelf/archive/2004/10/31/161024.aspx
SetWindowLong ,GWL_WNDPROC 不就是需要一个函数指针吗?子不过C# 生明 api 的时候要有些变化。
这里是一个例子:http://www.msjogren.net/dotnet/eng/samples/dotnet_dynpinvoke.asp
C# 支持调用C 的函数指针
不过要用 委托代替。loadlibrary C#里没用过 ,不过给你一个 类似的调用函数指针的列子。
//声明一个委托 public delegate IntPtr NewWndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); //把最后一个参数生命为 委托
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, NewWndProc wndproc);//实列化委托(这里就是回调函数) wpr= new NewWndProc(this.TextBoxWndProc); //替换控件的默认处理函数(并且返回原始的 默认处理函数,是一个函数指针的地质) oldWndProc=SetWindowLong(textBox1.Handle,GWL_WNDPROC,wpr);------------------------------------------------------------
http://blog.csdn.net/flashelf/archive/2004/10/31/161024.aspx
SetWindowLong ,GWL_WNDPROC 不就是需要一个函数指针吗?子不过C# 生明 api 的时候要有些变化。
俺的想法也是可行的,我试过了。
我没有试过。
Assembly MyAssembly = Assembly.Load(AssemblyName);//AssemblyName DLL的名字
ISDServer.IRetrieval Rx = (ISDServer.IRetrieval)(MyAssembly.CreateInstanceAssemblyName+".Retrieval"));
return Rx.Execute((ISDServer.IProcess)this,sServiceID,sParam);
里面只是根据UnmanagedType来决定生成的delegate的参数类型.所以没有针对 void** 这样的参数进行处理.其实帮定非托管函数的重点是参数类型的封送处理.给个提示,void*可以影射为object或IntPtr,而void**则影射为ref object或ref IntPtrusing System;
using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;namespace LostinetSample.InvokeDll
{
/// <summary>
/// Class1 的摘要说明。
/// </summary>
class Class1
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
DllService ds=new DllService("user32.dll","MessageBoxW"
,CharSet.Unicode
,new UnmanagedType[]
{
UnmanagedType.U4
,UnmanagedType.LPTStr
,UnmanagedType.LPTStr
,UnmanagedType.U4
}
); ds.Invoke((UInt32)0,"Hello","World",(UInt32)0);
}
}
}
namespace LostinetSample.InvokeDll
{
public class DllService
{
static Hashtable cachedAssemblies=new Hashtable();
static object creationlock=new object(); Delegate func;
Type[] argTypes; public DllService(string dllfile,string funcname,CharSet charset
,UnmanagedType[] umtypes)
: this(dllfile,funcname,charset,umtypes,UnmanagedType.AsAny,true)
{
}
public DllService(string dllfile,string funcname,CharSet charset
,UnmanagedType[] umtypes,UnmanagedType retumtype)
: this(dllfile,funcname,charset,umtypes,retumtype,false)
{
}
public DllService(string dllfile,string funcname,CharSet charset
,UnmanagedType[] umtypes,UnmanagedType retumtype,bool retVoid)
{
if(dllfile==null)throw(new ArgumentNullException("dllfile"));
if(funcname==null)throw(new ArgumentNullException("funcname"));
if(umtypes==null)umtypes=new UnmanagedType[0]; Type retType;
if(retVoid)
retType=typeof(void);
else
retType=GetUnmanagedType(retumtype); argTypes=GetUnmanagedTypes(umtypes); string key=dllfile+":"+funcname; lock(cachedAssemblies.SyncRoot)
{
func=(Delegate)cachedAssemblies[key];
}
if(func!=null)return; lock(creationlock)
{
lock(cachedAssemblies.SyncRoot)
{
func=(Delegate)cachedAssemblies[key];
}
if(func!=null)return; AssemblyName asmname=new AssemblyName();
asmname.Name="assemblyfor"+func+"_"+key.GetHashCode();
AssemblyBuilder asmbulder=AppDomain.CurrentDomain.DefineDynamicAssembly(asmname
,AssemblyBuilderAccess.Run
); ModuleBuilder mdlbuilder=asmbulder.DefineDynamicModule(asmname.Name); TypeBuilder typeBuilder=mdlbuilder.DefineType("ClassFor"+func
,TypeAttributes.Class|TypeAttributes.Public); MethodBuilder mthbuilder=typeBuilder.DefinePInvokeMethod(funcname,dllfile,funcname
,MethodAttributes.Public|MethodAttributes.Static|MethodAttributes.PinvokeImpl
,CallingConventions.Standard
,retType
,argTypes
,CallingConvention.StdCall
,charset
); if(!retVoid)
{
mthbuilder.SetMarshal(UnmanagedMarshal.DefineUnmanagedMarshal(retumtype));
}
for(int i=0;i<umtypes.Length;i++)
{
mthbuilder.DefineParameter(i+1
,ParameterAttributes.In,"param"+i);
}
TypeBuilder dgTypeBuilder=mdlbuilder.DefineType("DelegateOf"+funcname
,TypeAttributes.Class|TypeAttributes.Public|TypeAttributes.Sealed,typeof(MulticastDelegate)); ConstructorBuilder ctorBuilder=dgTypeBuilder.DefineConstructor(MethodAttributes.Public,CallingConventions.Standard,new Type[]{typeof(object),typeof(IntPtr)});
ctorBuilder.SetImplementationFlags(MethodImplAttributes.Managed|MethodImplAttributes.Runtime); MethodBuilder invokeBuilder=dgTypeBuilder.DefineMethod("Invoke",MethodAttributes.Public,CallingConventions.Standard,retType,argTypes);
invokeBuilder.SetImplementationFlags(MethodImplAttributes.Managed|MethodImplAttributes.Runtime); for(int i=0;i<umtypes.Length;i++)
{
invokeBuilder.DefineParameter(i+1
,ParameterAttributes.In,"param"+i);
}
Type resultType=typeBuilder.CreateType();
MethodInfo method=resultType.GetMethod(funcname,BindingFlags.Static|BindingFlags.Public); Type dgType=dgTypeBuilder.CreateType();
func=Delegate.CreateDelegate(dgType,method); lock(cachedAssemblies.SyncRoot)
{
cachedAssemblies[key]=func;
}
}
} Type GetUnmanagedType(UnmanagedType umtype)
{
switch(umtype)
{
case UnmanagedType.Bool:
return typeof(bool);
case UnmanagedType.BStr:
return typeof(string);
case UnmanagedType.Currency:
return typeof(decimal);
case UnmanagedType.Error:
return typeof(UInt32);
case UnmanagedType.FunctionPtr:
return typeof(IntPtr);
case UnmanagedType.I1:
return typeof(byte);
case UnmanagedType.I2:
return typeof(short);
case UnmanagedType.I4:
return typeof(int);
case UnmanagedType.I8:
return typeof(long);
case UnmanagedType.IDispatch:
case UnmanagedType.Interface:
case UnmanagedType.IUnknown:
return typeof(object);
case UnmanagedType.LPArray:
return typeof(object[]);
case UnmanagedType.LPStruct:
return typeof(object);
case UnmanagedType.LPStr:
case UnmanagedType.LPTStr:
case UnmanagedType.LPWStr:
return typeof(string);
case UnmanagedType.R4:
return typeof(float);
case UnmanagedType.R8:
return typeof(double);
case UnmanagedType.SafeArray:
return typeof(object[]);
case UnmanagedType.Struct:
return typeof(object);
case UnmanagedType.SysInt:
return typeof(long);
case UnmanagedType.SysUInt:
return typeof(UInt64);
case UnmanagedType.TBStr:
return typeof(string);
case UnmanagedType.U1:
return typeof(byte);
case UnmanagedType.U2:
return typeof(UInt16);
case UnmanagedType.U4:
return typeof(UInt32);
case UnmanagedType.U8:
return typeof(UInt64);
case UnmanagedType.VariantBool:
return typeof(bool);
case UnmanagedType.VBByRefStr:
case UnmanagedType.CustomMarshaler:
default:
throw(new NotSupportedException(umtype.ToString()));
}
}
Type[] GetUnmanagedTypes(UnmanagedType[] umtypes)
{
int len=umtypes.Length;
Type[] types=new Type[len];
for(int i=0;i<len;i++)
{
types[i]=GetUnmanagedType(umtypes[i]);
}
return types;
}
public object Invoke(params object[] args)
{
return func.DynamicInvoke(args);
}
}
}
其实只要使用method.Invoke就可以了。