Page 1 of 2 12 LastLast
Results 1 to 10 of 13

Thread: Executing procedure by it address

  1. #1

    Executing procedure by it address

    OS/Hardware: irrelevant, the question is pure technical - no errors
    IDE: Lazarus
    Api: None.
    -------------------------------
    I already posted this on Lazarus forum, but I don't got any response that I can use (this will very important for PlayMaker runtime)

    Let's say that I have name of procedure or function as string. How to get procedure address of that function/proc and then execute it (normally I will use proc(parameters), but how with calling by proc address?). I do not want to checking it in long if..else, because procedures will be lot.

    The only answer that I got was that I should use dynamic library and GetProcAddress. But was is the sense for making library that will be used only once, in one program?

  2. #2
    PGD Community Manager AthenaOfDelphi's Avatar
    Join Date
    Dec 2004
    Location
    South Wales, UK
    Posts
    1,245
    Blog Entries
    2

    Re: Executing procedure by it address

    Well, if the method is part of a class and you know it's name, you can get the address. You obviously need to know the function prototype so the compiler can validate the call, but it is relatively straight forward, and I wrote a tutorial about this thats available in the library here.

    In terms of standard routines, it is also possible, this time using getProcAddress. Here's an example:-

    [pascal]
    unit formMain;

    interface

    uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, StdCtrls;

    type
    TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    private
    { Private declarations }
    public
    { Public declarations }
    end;

    var
    Form1: TForm1;

    implementation

    {$R *.dfm}

    procedure method1;
    begin
    showMessage('Hello world 1');
    end;

    procedure method2;
    begin
    showMessage('Hello world 2');
    end;

    type
    TMyMethod = procedure;

    procedure TForm1.Button1Click(Sender: TObject);
    var
    mp : TMyMethod;
    begin
    @mp:=GetProcAddress(getModuleHandle(nil),'method1' );

    mp;
    end;

    exports
    method1,
    method2;

    end.
    [/pascal]

    The key thing with this is the exports section. If you don't include it, it will go bang.

    Hope this helps.
    :: AthenaOfDelphi :: My Blog :: My Software ::

  3. #3

    Re: Executing procedure by it address

    This will works on Linux too?


  4. #4
    PGD Community Manager AthenaOfDelphi's Avatar
    Join Date
    Dec 2004
    Location
    South Wales, UK
    Posts
    1,245
    Blog Entries
    2

    Re: Executing procedure by it address

    Quote Originally Posted by Darkhog
    This will works on Linux too?
    Didn't consider Linux to be honest, and I'm not able to say yes or no. The method used in my tutorial for accessing class methods should work as a similar mechanism should exist I believe. The getProcAddress approach... I can't say. Theoretically, if the calls exist it will be possible... if they don't then there may be an alternative you can use.

    Of course much of this could potentially be irrelevant, depending on what it is you are trying to achieve exactly, and how this will be used. If you don't want to openly discuss it, drop me a PM or email, but some more details about what it is you are trying to do with this mechanism may present other options.
    :: AthenaOfDelphi :: My Blog :: My Software ::

  5. #5

    Re: Executing procedure by it address

    Nope. Procedure getModuleHandle don't exist in LAZARUS. And please don't give me code for Delphi, because this simply don't work, on Linux

  6. #6

    Re: Executing procedure by it address

    I'll see if I can come up with something...

  7. #7
    PGD Community Manager AthenaOfDelphi's Avatar
    Join Date
    Dec 2004
    Location
    South Wales, UK
    Posts
    1,245
    Blog Entries
    2

    Re: Executing procedure by it address

    Quote Originally Posted by Darkhog
    Nope. Procedure getModuleHandle don't exist in LAZARUS. And please don't give me code for Delphi, because this simply don't work, on Linux
    First up, I don't see a massive number of replies, and given you've already asked the question on the Lazarus forums and gotten no replies... any information you get should be gratefully received as a possible solution or even better, a pointer to possible solutions.

    Secondly, your statement about code for Delphi not working on Linux. Thats not strictly true. I have a cross platform (Windows/Linux) service that compiles with Delphi and Kylix, the wrapper is different as one is a service whilst the other is a daemon, but the core code itself is the same, so it's not that Delphi (or more accurately Object Pascal) won't work on Linux, it's a case of some of the features available within Delphi, namely the Windows API do not have equivalent functions under Linux. So, this rules out the example code I provided which makes use of getProcAddress... but did you read the article I pointed you to?

    That utilises methodAddress, which of course means you can only find the address of a method of a class, but it DOES work with Free Pascal. Lazarus is built on Free Pascal is it not?

    I hope you can see now why I asked for more information about what and how you were going to use it. The code I presented is more flexible in that you aren't limited to class methods, but it may not work everywhere, whilst the methodAddress approach is limited to class methods, but it does work everywhere because its a core language feature.

    In future I would suggest you adopt a slightly more grateful tone when replying to someone who is trying to help. If you don't, people will pretty quickly stop helping.

    So, I'll reiterate my questions... how are you planning on using this? Can the routines you want to call be class methods? If not, why not? If they can, the methodAddress approach can be used... although from a performance point of view, there may be better approaches. A more object orientated method for example.
    :: AthenaOfDelphi :: My Blog :: My Software ::

  8. #8

    Re: Executing procedure by it address

    Hah!!!! Found it... It's almost the same as Athena's example....

    First off... add dynlibs to your uses clause...

    Now...

    [pascal]
    var
    Form1: TForm1;
    Adress: TLibHandle; //This is very important.

    implementation

    procedure Method1;
    begin
    ShowMessage('Hello world 1');
    end;

    procedure Method2;
    begin
    ShowMessage('Hello World 2');
    end;

    type
    TMyMethod = procedure; stdcall;

    procedure TForm1.Button1Click(Sender: TObject);
    var
    mp: TMyProcedure;
    begin
    mp := TMyProcedure(GetProcAdress(Adress, 'Method1'));

    mp;
    end;

    //This is very important, declare exports for each exported method...
    exports Method1 name 'Method1';
    exports Method2 name 'Method2';

    end.

    [/pascal]

    And viola... I got it right, the GetProcAdress is in the dynlibs unit...

    And I have to thank the FPC mailing lists for this...

    IMO, it would be best to develop a dynamic library (*.so/*.dll) that contains the needed methods for your Game Development IDE. And then call from that.

  9. #9

    Re: Executing procedure by it address

    Thanks, PJP Dev. I'll try it. I will post it on Lazarus forums. Did you notice problems with DB? SMF get something like this very often, so i don't use it (some time ago I had to use it, and this wasn't good experience)

    //EDIT: It's give me design-time error exports clause only allowed in libs. Can you post whole unit, please?
    //EDIT #2: Silly me - I put exports before initialization.
    //EDIT #3: Identifier not found: TLibHandle

  10. #10

    Re: Executing procedure by it address

    Quote Originally Posted by Darkhog
    Thanks, PJP Dev. I'll try it. I will post it on Lazarus forums. Did you notice problems with DB? SMF get something like this very often, so i don't use it (some time ago I had to use it, and this wasn't good experience)

    //EDIT: It's give me design-time error exports clause only allowed in libs. Can you post whole unit, please?
    //EDIT #2: Silly me - I put exports before initialization.
    //EDIT #3: Identifier not found: TLibHandle
    First off... I didn't get any problems with SMF on my site yet, but thats a bit off-topic.

    Solution for EDIT #1: Comment the exports out while placing components on the form. This is the reason why I suggest making a dynamic library.

    Solution for EDIT #2: I did it and it worked for me... Nothing wrong with that.

    Solution for EDIT #3: Did you add dynlibs to the uses clause?
    [pascal]
    unit Unit1;

    {$mode objfpc}{$H+}

    interface

    uses
    Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls, dynlibs;
    [/pascal]
    TLibHandle is in dynlibs, so you'll need to add it.

    Here is my full source...

    [pascal]
    unit Unit1;

    {$mode objfpc}{$H+}

    interface

    uses
    Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls, dynlibs;

    type

    { TForm1 }

    TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    private
    { private declarations }
    public
    { public declarations }
    end;

    var
    Form1: TForm1;
    adress: TLibHandle;


    implementation

    procedure Method1;
    begin
    ShowMessage('Hello world 1');
    end;

    procedure Method2;
    begin
    ShowMessage('Hello World 2');
    end;

    type
    TMyMethod = procedure; stdcall;

    { TForm1 }

    procedure TForm1.Button1Click(Sender: TObject);
    var
    mp: TMyMethod;
    begin
    mp := TMyMethod(GetProcAddress(adress, 'Method1'));

    mp;
    end;

    procedure TForm1.Button2Click(Sender: TObject);
    var
    mp: TMyMethod;
    begin
    mp := TMyMethod(GetProcAddress(adress, 'Method2'));

    mp;
    end;

    exports Method1 name 'Method1';
    exports Method2 name 'Method2';

    initialization
    {$I Unit1.lrs}

    end.
    [/pascal]

Page 1 of 2 12 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •