技术: .NET C# 动态调用动态链接库中的函数。

翟二喜

C# 调用传统的 API 动态链接库,是.NET开发经常被讨论的问题。


比如有这么一个动态链接库(delphi 语言):


library DelphiDLL;

uses
  SysUtils,
  Classes,
  Windows;

{$R *.res}

function TestMyFunction( a: Integer ): Integer; stdcall;
begin
  Result := a * a;
end;

exports
  TestMyFunction;

begin
end.


在C#中调用这个动态链接库的一般方法是:


class DllStatic
{
  [DllImport( "DelphiDLL.dll" )]
  public static extern int TestMyFunction( int a );
}


但这种方法类似传统语言对动态链接库的“静态调用”(如 delphi 中的 external )。这种静态调用,有的时候并不是我们想要的。


在传统语言中,我们可以用 LoadLibrary、GetProcAddress 来替代上面的方法。经过思考的试验,在C#中,也可以使用这种方法来实现。


class DllDynamic
{
  [DllImport( "Kernel32.dll" )]
  public static extern int LoadLibrary( string lpFileName );

  [DllImport( "Kernel32.dll" )]
  public static extern bool FreeLibrary( int hModule );

  [DllImport( "Kernel32.dll" )]
  public static extern IntPtr GetProcAddress( int hModule, string lpProcName );
}

class Program
{
  public delegate int TestMyFunction( int a );


  static void Main( string[] args )
  {   
    int hLib = DllDynamic.LoadLibrary( "DelphiDLL.dll" );
    try
    {
      IntPtr ptr = DllDynamic.GetProcAddress( hLib, "TestMyFunction" );
     
TestMyFunction myfunc = (TestMyFunction) Marshal.GetDelegateForFunctionPointer( ptr, typeof( TestMyFunction ) );

      
for (int i = 0; i < 10; i++ )
      {
        Console.WriteLine( myfunc( i ) );
      }
    }
    finally
    {
      DllDynamic.FreeLibrary( hLib );
    }
  }
}


其中,对 GetProcAddress 的结果做何处理,是尝试多次的焦点问题。查找若干资料,终于发现 Marshal 类中的静态方法可以进行内存地址到函数托管的封存转换。

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

目前评论:1   其中:访客  0   博主  0

  1. 小G 5

    请问如果这个dll是纯资源文件呢,有没有像LoadString此类的方法去读取呢