C#动态调用C++生成的dll

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);// 调用方法,并返回其值

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值