动态设置 DllImport 属性

发布于 2024-08-31 21:28:42 字数 287 浏览 1 评论 0原文

我正在使用 PInvoke 和 DllImport 属性来使用外部非托管 dll。例如。

[DllImport("mcs_apiD.dll", CharSet = CharSet.Auto)]
private static extern byte start_api(byte pid, byte stat, byte dbg, byte ka);

我想知道是否可以以某种方式动态更改 dll 文件详细信息(本例中为 mcs_apiD.dll),例如,如果我想针对另一个 dll 版本进行构建

I am making use of an external unmanaged dll using PInvoke and the DllImport attribute. eg.

[DllImport("mcs_apiD.dll", CharSet = CharSet.Auto)]
private static extern byte start_api(byte pid, byte stat, byte dbg, byte ka);

I am wondering if it is possible to alter the dll file details (mcs_apiD.dll in this example) dynmically in some manner, if for instance I wanted to build against another dll version

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

毁梦 2024-09-07 21:28:42

是的,这是可能的,您必须完成 P/Invoke 编组器所做的部分工作。加载 DLL 并找到导出函数的入口点。首先声明一个签名与导出函数匹配的委托:

 private delegate byte start_api(byte pid, byte stat, byte dbg, byte ka);

然后使用如下代码:

 using System.ComponentModel;
 using System.Runtime.InteropServices;
  ...

    static IntPtr dllHandle;
  ...
        if (dllHandle == IntPtr.Zero) {
            dllHandle = LoadLibrary("mcs_apiD.dll");
            if (dllHandle == IntPtr.Zero) throw new Win32Exception();
        }
        IntPtr addr = GetProcAddress(dllHandle, "_start_api@16");
        if (addr == IntPtr.Zero) throw new Win32Exception();
        var func = (start_api)Marshal.GetDelegateForFunctionPointer(addr, typeof(start_api));
        var retval = func(1, 2, 3, 4);
  ...
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr LoadLibrary(string name);
    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
    private static extern IntPtr GetProcAddress(IntPtr hModule, string name);

当然有很多方法会出错。请注意,您必须使用 DLL 中实际导出的名称,您不再获得 P/Invoke 编组器的帮助来帮助进行名称修饰。如果您不确定导出名称是什么样子,请在 DLL 上使用 dumpbin.exe /exports。

Yes this is possible, you'll have to do part of the job that the P/Invoke marshaller does. Loading the DLL and finding the entry point of the exported function. Start by declaring a delegate whose signature matches the exported function:

 private delegate byte start_api(byte pid, byte stat, byte dbg, byte ka);

Then use code like this:

 using System.ComponentModel;
 using System.Runtime.InteropServices;
  ...

    static IntPtr dllHandle;
  ...
        if (dllHandle == IntPtr.Zero) {
            dllHandle = LoadLibrary("mcs_apiD.dll");
            if (dllHandle == IntPtr.Zero) throw new Win32Exception();
        }
        IntPtr addr = GetProcAddress(dllHandle, "_start_api@16");
        if (addr == IntPtr.Zero) throw new Win32Exception();
        var func = (start_api)Marshal.GetDelegateForFunctionPointer(addr, typeof(start_api));
        var retval = func(1, 2, 3, 4);
  ...
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr LoadLibrary(string name);
    [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
    private static extern IntPtr GetProcAddress(IntPtr hModule, string name);

Lots of ways to get this wrong of course. Do note that you have to use the actual exported name from the DLL, you no longer get the help from the P/Invoke marshaller to help with name decoration. Use dumpbin.exe /exports on the DLL if you are not sure what the export name looks like.

雄赳赳气昂昂 2024-09-07 21:28:42

您无法更改 dll 的名称,但可以更改正在加载的库的路径(例如从注册表或配置文件中读取它)并使用 LoadLibrary kernel32 的函数手动加载它: 在那里查看我的答案

you can't change the name of the dll but you can alter the path of the library being loaded (like by reading it from the registry or a configuration file) and load it manually with LoadLibrary kernel32's function: see my answer there.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文