我有一个c dll,并想通过C#动态加载它。我是这样的:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace Dota2Plugins
{
class Interop
{
#region Win API
[DllImport("kernel32.dll")]
private extern static IntPtr LoadLibrary(string lpLibFileName);
[DllImport("kernel32.dll")]
public extern static IntPtr GetProcAddress(IntPtr hLib, string lpProcName);
[DllImport("kernel32.dll")]
public extern static bool FreeLibrary(IntPtr hLib);
#endregion
private IntPtr hLib;
public Interop(String DLLPath)
{
hLib = LoadLibrary(DLLPath);
if (hLib == IntPtr.Zero)
{
throw new Exception("not found dll : " + DLLPath);
}
}
~Interop()
{
FreeLibrary(hLib);
}
public IntPtr GetIntPtr(string APIName)
{
IntPtr api = GetProcAddress(hLib, APIName);
if (api == IntPtr.Zero)
{
throw new Exception("not found api : " + APIName);
}
return api;
}
public Delegate GetDelegate(string APIName, Type t)
{
IntPtr api = GetIntPtr(APIName);
return Marshal.GetDelegateForFunctionPointer(api, t);
}
}
}
像这样加载dll:
Interop interop =新的Interop(“ KeyBoardHook.dll”);`
但是当我运行我的应用程序时,它会抛出错误:
未找到dll:KeyBoardHook.dll
我已将dll复制到应用程序目录。
我使用相对目录和绝对目录进行尝试,并得到相同的错误结果。
如何在C#中动态加载c DLL并调用DLL导出api?
答案 0 :(得分:1)
您提出了两个问题,首先,找不到DLL,以及如何从C中进行动态加载。
当尝试从C#32位项目加载X64 dll时,这是一个常见问题。
public Interop(String DLLPath)
开始时尝试过File.Exists?也许您的应用程序目录不正确,如Stefan在评论中所述。
也尝试完整路径。
关于动态加载,这是另一个主题。您必须在DLL中指定参数,理论上可以在运行时进行设置。
如果有标头,则可以创建一个从System.Dynamic.DynamicObject
派生的类,并在运行时解析标头,从TryInvokeMember
覆盖(一旦获得,就可以对其进行解析)。
我不会使用这种方法。
恐怕我不确定如何在没有标题的情况下动态地进行操作。
答案 1 :(得分:0)
我相信您的声明是错误的,据我所知您应该:
[DllImport("kernel32", SetLastError=true, CharSet = CharSet.Ansi)]
private static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);
[DllImport("kernel32", CharSet=CharSet.Ansi, ExactSpelling=true, SetLastError=true)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll", SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool FreeLibrary(IntPtr hModule);
我正在从http://pinvoke.net那里取走这些东西。
您面临的问题很可能是由于C#默认将string
编组为BStr
(长度为前缀的字符串)(documentation),但是将{{1} }将解析为LoadLibraryA
,它期望以null结尾的ansi字符串(LoadLibrary
)。
您可能还对Vanara.PInvoke.Kernel32(NuGet,Repository)感兴趣,因为它及其配套库具有您可能需要的所有Windows API定义。