Subscribe for automatic updates: RSS icon RSS

Login icon Sign in for full access | Help icon Help
Advanced search

Pages: [1]
  Reply  |  Print  
Author Topic: Dynamic function calls  (Read 16004 times)
Snorri B.
Posts: 104


« on: July 18, 2008, 04:11:21 pm »

Hi everyone.

Is there an [un]documented way in BDL to call a function dynamically, like

call CallFunction("funcname", "[parameters...]") returning .....

I recall some discussion about this few years ago, but I can't find it.

Best regards,
-Snorri
David H.
Posts: 158


« Reply #1 on: July 18, 2008, 05:00:13 pm »

Hi Snorri,

I use fCall() directly or in Genero v2+ a #defined fCall (to fglcapi_call4gl(aName,anArgC)) in our C runner to give us this functionality. I discovered this whilst poking around in fglext.h one day. You have to push/pop your parameters. We use this to provide a dynamic callback mechanism in our central picklist control and its works very well.

Something built directly into BDL would be nice in a future version. Hopefully something for v2.20+..!

Regards,

David
Snorri B.
Posts: 104


« Reply #2 on: July 18, 2008, 05:33:32 pm »

Thanks David.

Could you perhaps (if it's not too much work for you) send me an example how this works?

Best regards, and have a nice weekend
-Snorri
David H.
Posts: 158


« Reply #3 on: July 21, 2008, 11:05:17 am »

Hi Snorri,

Hope this brief example will give you a better idea. Apart from the odd typo it should work... Allegedly!

C Runner...

Code
  1. //for Genero V2+
  2. #define fCall(aName,anArgC)   fglcapi_call4gl(aName,anArgC)
  3. //Simple function call with 1 parameter and single return parameter.
  4. int call_4gl(int nargs)
  5.  
  6. { char funcname[100];
  7.  long recno;
  8.  short status;
  9.  
  10.  poplong(&recno);            //get argument for 4GL call
  11.  popvchar(funcname,99);      //get function name for 4GL call
  12.  pushlong(recno);            //push argument for call to 4GL
  13.  fCall(funcname,1);          //call 4gl function with single parameter
  14.  popshort(&status);          //get functions return parameter
  15.  retshort(status);           //return to caller
  16.  return(1);
  17. }


4GL

   
Code
  1.    FUNCTION fetch_prod(l_prod_unique_key)
  2.  
  3.        DEFINE l_prod_unique_key INTEGER
  4.  
  5.        SELECT * INTO g_prod_rec.*
  6.            WHERE prod_unique_key = l_prod_unique_key
  7.  
  8.        RETURN status = 0
  9.  
  10.    END FUNCTION
  11.  
  12.  
  13.    MAIN
  14.  
  15.        DEFINE l_ok         SMALLINT
  16.        DEFINE l_unique_key INTEGER
  17.  
  18.        PROMPT "Record to fetch?" FOR l_unique_key
  19.        CALL call_4gl("fetch_prod",l_unique_key) RETURNING l_ok
  20.  
  21.    END MAIN

Regards,

David

Snorri B.
Posts: 104


« Reply #4 on: July 21, 2008, 11:54:51 am »

Thanks a lot!

I will try this out ASAP.

Regards,
-Snorri
Andrew C.
Posts: 48


« Reply #5 on: August 12, 2008, 08:11:42 am »

Or you might like this variation which supports any number of arguments and return values

int c_call_fz(int nargs) {
    char ftn[51];

    if(nargs-- == 0)
        cfgl_fatal("usage: c_call_fz([args, ...] ftnname char(*)) [returning values...]");
    poptrim(ftn, sizeof(ftn));
    return fglcapi_call4gl(ftn, nargs);
}   /* c_call_fz */

poptrim() is just a little function of mine which pops a char string and blank-trims it, no trouble for anyone to write that.

cfgl_fatal() is a function I use for uniform reporting of failure to call a C function properly, followed by program termination (programmers better deal with the fault Codd-damn it or they ain't getting a running program!)

You'll notice that the name of the function is at the end (reflected in my mnemonic _fz wart at the end of the function name). I did this because getting it from the bottom of the stack is too much hard work. I had a version that would do that, but it could not cope with data types like datetimes, etc. So I decided to put the function name at the end, and indicate it's a dodgy interim version of the function by naming it with the _fz wart. One day a first-class c_call might be possible...

In your fglext.c, you just need

    { "c_call_fz",              c_call_fz,                  -1,  -1 },

to make fgl2p happy compiling this function with variable arg and return lists, you need to use the -z flag and a file that lists this function:


    fgl2p -z /somewhere/varargftns.lst thingy.4gl

where my /somewhere/varargftns.lst contains something like

c_call_fz -1 -1

amongst others


given all the conditions mentioned above, the same .4gl file can call


    call c_call_fz("ftn1")
    call c_call_fz(1, 2, "ftn2") returning a, b, c

and so on without getting compile time errors.
Evandro S.
Posts: 4


« Reply #6 on: October 04, 2024, 09:44:24 pm »

Hey Andrew,

Thanks for sharing your dynamic function call, it help me a lot!

I have just one doubt for now:
     if i want to pass dynamic parameters, how could i do it?
Sebastien F.
Four Js
Posts: 545


« Reply #7 on: October 05, 2024, 05:04:15 am »

Hello Evandro,

It's a while since this topic has been discussed here.

What version of Genero BDL are you using?

Instead of C Extensions, you should consider new features added in recent versions of Genero BDL such as:

- https://4js.com/online_documentation/fjs-fgl-manual-html/index.html#fgl-topics/c_fgl_Functions_references.html

- https://4js.com/online_documentation/fjs-fgl-manual-html/index.html#fgl-topics/c_fgl_Interface_intro.html

Seb
Evandro S.
Posts: 4


« Reply #8 on: October 05, 2024, 08:39:00 pm »

Hi Seb

I am using 3.20 version.

In the references you have sent, i cant see how can i call a function using a string for its name.

I am needing something like this:

Let str = "myfunc('aaa',999)" #func name and parameters dynamic
Call str

And if the func has return values, i need to get it in any way (maybe in an array os returned values)
Sebastien F.
Four Js
Posts: 545


« Reply #9 on: October 06, 2024, 10:54:22 am »

Hi Evandro,

First, you should be using 3.21 not 3.20 because last one is no longer supported.
You should even consider moving to version 5.00.

You need to properly understand the concept to function references in Genero.

The solution we provide is not based on function names as strings, and is not designed to handle a variable set of parameters or return values.

We use a different approach with static function signatures, to have a better control at compile time and at runtime.

Using C extensions with full-dynamic names, variable parameters and return values looks flexible but is subject of mistakes.

I would be interested to know how many functions you need to call dynamically, and the overall context for this need.

We can offer you help through our Professional Services team, please contact us directly.

Seb
Evandro S.
Posts: 4


« Reply #10 on: October 07, 2024, 01:32:17 pm »

Hi Seb,

We are testing v5 and we planning this upgrade to 2025.

The context is an integrator, where users can configure in a user interface the function and parameters to execute receiving requests through API or via crontab.

I already know the concept of functions in 4gl and genero, and i know that all is possible simplyly programming a new static 4gl program for each integration i want to... but i'm looking to do something different, smarter and easy to use.

i know too that we could have professional support, but as i've found this article of someone doing something similar to what i need, it was the reason i'm here asking for help.
Pages: [1]
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines