C++中的方法int MyFun(int a,int b);
生成dll文件:MyDll.dll
在C#中调用dll文件一般需要声明:
[DllImport("MyDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int MyFun( int a, int b);
这样想动态来加载dll没办法操作。
后来在网上查了下,有两种方式能够动态的加载dll,不用声明:
先准备好DllInvoke类
public class DllInvoke
{
#region Win API
[DllImport("kernel32.dll")]
private extern static IntPtr LoadLibrary(string path);
[DllImport("kernel32.dll")]
private extern static IntPtr GetProcAddress(IntPtr lib, string funcName);
[DllImport("kernel32.dll")]
private extern static bool FreeLibrary(IntPtr lib);
#endregion
private IntPtr hLib;
public DllInvoke(String DLLPath)
{
hLib = LoadLibrary(DLLPath);
if (hLib == IntPtr.Zero)
{
throw (new Exception("没有找到:" + DLLPath + "。"));
}
}
~DllInvoke()
{
FreeLibrary(hLib);
}
public IntPtr GetIntPtr(string APIName)
{
IntPtr api = GetProcAddress(hLib, APIName);
if (api == IntPtr.Zero)
{
throw (new Exception(" 没有找到 :" + APIName + " 这个函数的入口点 "));
}
return api;
}
//将要执行的函数转换为委托
public Delegate GetDelegate(string APIName, Type t)
{
IntPtr api =GetIntPtr(APIName);
return (Delegate)Marshal.GetDelegateForFunctionPointer(api, t);
}
}
方法一:
delegate int Add(IntPtr[] X, int r, int c);
DllInvoke dk = new DllInvoke("MyDll.dll");
Add addFunction = (Add)dk.GetDelegate("MyFun", typeof(Add));
int sum=addFunction(2,3);
方法二:
object[] par = new object[] {2,3 };//输入参数
Type[] parType = par.Select(s=>s.GetType()).ToArray();//输入参数的类型
//Type[] parType =new Type[]{typeof(int),typeof(int)};
Type Type_Return = typeof(int); // 返回类型
AssemblyName assemblyName = new AssemblyName("InvokeName");//名称随便写
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("InvokeModule");
MethodBuilder methodBuilder = moduleBuilder.DefineGlobalMethod("InvokeMethod", MethodAttributes.Public | MethodAttributes.Static, Type_Return, parType);
ILGenerator IL = methodBuilder.GetILGenerator();
for (int i = 0; i < par.Length; i++)
{// 依次压入堆栈
IL.Emit(OpCodes.Ldarg, i); //实参传送方式,byValue
// IL.Emit(OpCodes.Ldarga, i);//实参传送方式,byRef
}
//要调用的dll
DllInvoke dk = new DllInvoke("MyDll.dll");
//调用的方法
IntPtr farProc = dk.GetIntPtr("MyFun");
if (IntPtr.Size == 4)
{// 判断处理器类型
IL.Emit(OpCodes.Ldc_I4, farProc.ToInt32());
}
else if (IntPtr.Size == 8)
{
IL.Emit(OpCodes.Ldc_I8, farProc.ToInt64());
}
else
{
throw new PlatformNotSupportedException();
}
IL.EmitCalli(OpCodes.Calli, CallingConvention.StdCall, Type_Return, parType);
IL.Emit(OpCodes.Ret);
moduleBuilder.CreateGlobalFunctions();
//方法名和上面的一致
MethodInfo MyMethodInfo = moduleBuilder.GetMethod("InvokeMethod");
object sum = MyMethodInfo.Invoke(null, par);// 调用方法,并返回其值