Putting classes in a DLL?

后端 未结 4 1249
走了就别回头了
走了就别回头了 2020-12-03 08:51

Is it possible to put some classes into a DLL?

I have several custom classes in a project I am working on and would like to have them put in a DLL and then accessed

相关标签:
4条回答
  • 2020-12-03 09:24

    While the official answer is "you can't", anything is possible of course. Frameworks like Remobjects SDK and Remobjects Hydra has been doing this for a long time. The problem is that it requires you to create an infrastructure around such a system, which is not something Delphi deals with out of the box.

    The first step is memory management. A DLL is injected into the process loading it, but it does not share memory management. It has to be this way since a DLL can be created in a myriad of languages, each with their own internal mechanisms. This poses a problem with safety (i.e program writing into DLL memory and visa versa).

    Secondly, interface (read: content description). How will your application know what classes it can create, class members, parameter types and so on. This is why COM requires type-libraries, which describe the content of a DLL.

    Third, life-time management. If memory management for the objects created from a DLL is handled by the DLL, the DLL must also release said objects.

    The above steps already exists and it's called COM. You are of course free to create as many COM DLL files as you please, just remember that these have to be registered with Windows before you use them. Either "on the fly" by your application (if you have the security rights to do so) or by your installer. This is why COM, while representing the ultimate plugin system, is rarely used by Delphi programmers, because the technical cost of using it as a plugin system outweighs the benefits.

    The alternative way

    If you can assure that your DLL's are only to be used by Delphi programs, then you have a second way to explore. You have to create methods to share the memory manager of your main program with the DLL (Remobjects does this). This allows you to share objects, strings and more between the DLL and the main application.

    You can then use RTTI to "map" classes stored in the DLL (the DLL must do this and generate both class and method tables) which can be invoked through a proxy class you device yourself.

    All in all, unless you have plenty of free time to waste, I would either buy a system like Remobjects Hydra - or stick with packages. But can it be done another way? Of course it can. But at the cost of time and hard work.

    0 讨论(0)
  • 2020-12-03 09:32

    It is not possible to get a Class/Instance from a DLL. Instead of the class you can hand over an interface to the class. Below you find a simple example

    // The Interface-Deklaration for Main and DLL
    unit StringFunctions_IntfU;
    
    interface
    
    type
      IStringFunctions = interface
        ['{240B567B-E619-48E4-8CDA-F6A722F44A71}']
        function CopyStr( const AStr : WideString; Index, Count : Integer ) : WideString;
      end;
    
    implementation
    
    end.
    

    The simple DLL

    library StringFunctions;
    
    uses
      StringFunctions_IntfU; // use Interface-Deklaration
    
    {$R *.res}
    
    type
      TStringFunctions = class( TInterfacedObject, IStringFunctions )
      protected
        function CopyStr( const AStr : WideString; Index : Integer; Count : Integer ) : WideString;
      end;
    
      { TStringFunctions }
    
    function TStringFunctions.CopyStr( const AStr : WideString; Index, Count : Integer ) : WideString;
    begin
      Result := Copy( AStr, Index, Count );
    end;
    
    function GetStringFunctions : IStringFunctions; stdcall; export;
    begin
      Result := TStringFunctions.Create;
    end;
    
    exports
      GetStringFunctions;
    
    begin
    end.
    

    And now the simple Main Program

    uses
      StringFunctions_IntfU;  // use Interface-Deklaration
    
    // Static link to external function
    function GetStringFunctions : IStringFunctions; stdcall; external 'StringFunctions.dll' name 'GetStringFunctions';
    
    procedure TMainView.Button1Click( Sender : TObject );
    begin
      Label1.Caption := GetStringFunctions.CopyStr( Edit1.Text, 1, 5 );
    end;
    
    0 讨论(0)
  • 2020-12-03 09:40

    Use runtime packages for this purpose; it's exactly what they're designed for in the first place. They get loaded automatically (or can be loaded manually), and automatically set up the sharing of the same memory manager so you can freely use classes and types between them.

    You're much better off using packages (which is exactly what the IDE does for much of its functionality for that very reason).

    0 讨论(0)
  • 2020-12-03 09:43

    Delphi does not support either importing or exporting classes from DLLs. To import a class from another module, you need to use packages.

    0 讨论(0)
提交回复
热议问题