看看动态库创建与使用相关的东西
生成与使用(托管的)dll
-
dll.cs ==> dll.dll
// file: dll.cs
public class Calc
{
public static int Add(int a, int b)
{
return a + b;
}
}
-
main.cs ==> main.exe
// file: main.cs
using System;
class App
{
public static void Main()
{
Console.WriteLine("{0} + {1} = {2}", 123, 456, Calc.Add(123, 456));
}
}
编译:
E:\> csc /target:library dll.cs E:\> csc /reference:dll.dll main.cs
运行:
E:\> main 123 + 456 = 579
动态加载dll
using System;
using System.Reflection;
class App
{
public static void Main()
{
Assembly dll = Assembly.Load("dll");
Type calcType = dll.GetType("Calc");
object[] parameters = new object[]{123, 456};
object res = calcType.InvokeMember("Add2",
BindingFlags.Default | BindingFlags.InvokeMethod,
null,
null,
parameters);
Console.WriteLine("{0} + {1} = {2}", 123, 456, (int)res);
}
}
- 首先,加载我们动态库dll.dll,使用的Assembly.Load,也可以用(相对或绝对路径)
Assembly.LoadFrom("dll.dll");
- 然后,获取需要的类型,存于calcType
-
最后通过InvokeMember调用该类型中的成员函数。如果调用的不是static成员,还需要创建该类型的实例
Object obj = Activator.CreateInstance(calcType);
object res = calcType.InvokeMember("Add",
BindingFlags.Default | BindingFlags.InvokeMethod,
null,
obj,
parameters);
另一种写法:
MethodInfo addMethod = calcType.GetMethod("Add");
object[] parameters = new object[]{123, 456};
object obj = Activator.CreateInstance(calcType);
object res = addMethod.Invoke(obj, parameters);
使用非托管 dll
-
dll2.cpp ==> dll2.dll
// file: dll2.cpp
extern "C" int __declspec(dllexport) Add(int a, int b)
{
return a + b;
}
-
main.cs ==> main.exe
// file: main.cs
using System;
using System.Runtime.InteropServices;
class App
{
[DllImport("dll2.dll")]
public static extern int Add(int a, int b);
public static void Main()
{
Console.WriteLine("{0} + {1} = {2}", 123, 456, Add(123, 456));
}
}
编译运行:
E:\> cl dll2.cpp /LD E:\> csc main.cs E:\> main 123 + 456 = 579
这个东西被称为Platform Invoke(P/Invoke).DllImport还有一些属性
-
EntryPoint
-
CharSet
-
CallingConvention
-
SetLastError
[DllImport("dll2.dll", EntryPoint="Add", CharSet=CharSet.Auto, CallingConvention=CallingConvention.Winapi, SetLastError=true)]
动态加载dll
这又需要回到Win32 Api函数LoadLibrary、FreeLibrary这些东西了
// file: main.cs
using System;
using System.Runtime.InteropServices;
class App
{
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllFileName);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr dllHandle, string functionName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr dllHandle);
private delegate int AddDelegate(int a, int b);
public static void Main()
{
IntPtr handle = LoadLibrary("dll2.dll");
IntPtr pAddFunc = GetProcAddress(handle, "Add");
AddDelegate Add = (AddDelegate)Marshal.GetDelegateForFunctionPointer(
pAddFunc, typeof(AddDelegate));
Console.WriteLine("{0} + {1} = {2}", 123, 456, Add(123, 456));
FreeLibrary(handle);
}
}
先用P/Invoke把这3个函数弄进来,然后用它们去处理我们要动态加载的动态库。
直接编译
E:\> csc main.cs
本文介绍了如何创建与使用托管及非托管DLL文件。通过具体的代码示例,展示了使用C#进行DLL生成、静态链接和动态加载的过程,并演示了如何通过P/Invoke调用非托管DLL中的函数。
7195

被折叠的 条评论
为什么被折叠?



