开发者

C#调用非托管dll的两种方式详解

开发者 https://www.devze.com 2025-10-30 10:57 出处:网络 作者: 贪嘴
目录示例DLL方式一:直接调用方式二:使用本地委托辅助方法定义委托使用委托调用方法注意事项示例DLL
目录
  • 示例DLL
  • 方式一:直接调用
  • 方式二:使用本地委托
    • 辅助方法
    • 定义委托
    • 使用委托调用方法
  • 注意事项

    示例DLL

    首先,我们有一个Delphjsi编写的DLL,它导出了一个名为MyFunction的方法:

    library testDLL;
    
    uses
      SysUtils,
      Dialogs,
      Classes;
    
    {$R *.res}
    
    function MyFunction(param1: Integer): Integer; stdcall;
    begin
      Result := param1 + 1;
    end;
    
    exports
      MyFunction;
    
    begin
    end.
    

    方式一:直接调用

    这是最常见的调用方式,通过DllImport属性直接导入非托管方法。

    [DllImport("testDLL.dll")]
    static extern int MyFunction(int a);
    

    www.devze.com后,你可以直接调用这个方法:

    int i = MyFunction(123);
    

    方式二:使用本地委托

    另一种方法是将非托管方法转换为本地委托。这种方式更灵活,但需要更多的代码。

    辅助方法

    首先,我们需要一些python辅助方法来加载和卸载DLL:

    // 辅助方法:加载DLL
    [DllImport("kernel32.dll", SetLastError = true)]
    sphptatic extern IntPtr LoadLibrary(string lpFileName);
    
    // 辅助方法:卸载DLL
    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool FreeLibrary(IntPtr hModule);
    
    // 获取方法指针
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
    

    定义委托

    接下来,定义一个与DLL中方法参数一致的委托:

    public delegate int MyFunctionDelpwww.devze.comhiDelegate(int param1);
    

    使用委托调用方法

    最后,使用委托来调用非托管方法:

    void run()
    {
        // 加载DLL
        IntPtr dllHandle = LoadLibrary("testDLL.dll");
        if (dllHandle == IntPtr.Zero)
        {
            var err = Marshal.GetHRForLastWin32Error();
        }
    
        // 获取方法指针
        IntPtr functionPointer = GetProcAddress(dllHandle, "MyFunction");
    
        MyFunctionDelphiDelegate my = (MyFunctionDelphiDelegate)Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(MyFunctionDelphiDelegate));
        // 调用方法
        int i = my(1);
    
        // 释放DLL
        FreeLibrary(dllHandle);
    }
    

    注意事项

    1. 位数一致性:确保你的程序和DLL的位数(32位或64位)保持一致。
    2. 字符串参数:Delphi方法中的参数和返回值如果是字符串,不能直接使用String类型。需要使用PAnsiCharPChar,并搭配StrNew使用。
    3. 返回值:如果方法返回值为字符串,需要使用IntPtr类型,并通过Marshal.PtrToStringAnsi(strIntPtr)来获取实际的字符串值。

    通过这两种方式,你可以灵活地在C#中调用非托管的DLL库,满足不同的开发需求。

    到此这篇关于C#调用非托管dll的两种方式详解的文章就介绍到这了,更多相关C#调用非托管dll内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号