Home AMX User Forum NetLinx Studio

Calls and functions

What is better - to define function, or to define call? What is the difference between them? What is the difference between "call" and "system call"? I've read documentation, and understood "what" are them. Now i want to understand "why". Why and where should i use "call", "system call", or "function". Can anybody explain me, please?

Comments

  • a DEFINE_CALL is a subroutine, which can be used to operate anything. This can be just some simple code or a routine which will give you back a result.

    DEFINE_CALL 'SYSTEM_SHUTDOWN' // just a codeblock
    {
    // anything here necessary to shutdown the system
    }

    DEFINE_CALL 'CALCULATE'(VALUE1,VALUE2,RESULT) // operate with a result
    {
    RESULT = VALUE1 + VALUE2
    }


    A DEFINE_FUNCTION() is almost the same. It can be used just to operate some code, but, and this is the difference, it can also give you a result directly.

    DEFINE_FUNCTION SYSTEM_SHUTDOWN() // empty () must be written!!!
    {
    // any code to shutdown the system
    }

    DEFINE_FUNCTION CALCULATE(VALUE1,VALUE2)
    {
    STACK_VAR RESULT
    RESULT = VALUE1 + VALUE2
    RETRUN RESULT
    }


    The difference is that a CALL needs an additional variable to give you back a result.

    CALL 'CLACULATE'(MyValue1,MyValue2,MyResult)
    SEND_STRING 0,"'My result is ',ITOA(MyResult)"

    The FUNCTION can give you the result directly
    SEND_STRING 0,"'My result is ',ITOA(CALCULATE(MyValue1,MyValue2))"


    The SYSTEM_CALL is, in some simple words, a predefined DEFINE_CALL, saved into a .LIB file. It was the AXcess way to write a device driver, but has some disadvantages, like the code is readable for everyone, and you may also get trouble with variable names, waits, etc. In NetLinx the SYSTEM_CALL is replaced by the Modules.

    What I'll prefer, CALLs or FUNCTIONs....... well it's some kind of philosophy. I'm using FUNCTIONs only. The can give me a result directly, it's not necessary to keep track of upper/lowercase spelling the routine's name. And because programmers are lazy, it's less to write :-)

    SEND_STRING 0,"'My result is ',ITOA(cALcuLaTe(MyValue1,MyValue2))"

    Against
    CALL 'CALCULATE'(MyValue1,MyValue2,MyResult)
    SEND_STRING 0,"'My result is ',ITOA(MyResult)"

    I hope this will bring some light into the darkness....

    Regards,
  • Thank you for answer, Marc. I agree with you that to define functions is more easy, i use this method too, but there was some doubt about optimization...
    But you said, that SYSTEM_CALL's are now replaced with modules, and now i have a question about modules (maybe it would be better to create another thread with this question, but i don't think that such simple question must pollute forum). How does module operate with the main program? Is it only a "code block", containing event handlers, etc, which can be inserted in any program? Can i somehow use variables or constants, or functions, which were defined in module, in main program (like 'units' in PASCAL)?
  • vincenvincen Posts: 526
    In Fact Modules are some real programs running separately from main program. The two only differences between modules and programs are first line that is respectively MODULE_NAME or PROGRAM_NAME, and fact that modules can't run alone, they need to be instantiated from a main program.

    You can use variables, everything with a name, and give it same name as in main program, but they won't communicate, system will run one instance of each variable declared in program, and modules separate, so no risks of name conflict between main program and modules.

    Also one big advantage of modules is that you can distribute them in compiled form (as Inconcert modules from AMX for example), users don't need source code to include them in their program.

    The only communication channel between your program and your modules are variables you pass in your DEFINE_MODULE in main program to instantiate the module. Whatever main program or module writes in these variables, both are updated with new values.

    Also you can instantiate more than one time a same module in a program. Let's say your module manages communications with an IP or serial device, and you have more than one of these equipments, you can instantiate few times the same module, one time for each equipment. You only have to take care to give a distinct name for each instance in DEFINE_MODULE in your main program.

    Hope it clarifies use of modules ;)

    Vinc
  • Just a couple of precisions above Vincen's nice summary:
    vincen wrote:
    In Fact Modules are some real programs running separately from main program.

    Well, the *name space* is separate, but modules are *NOT* threads. That means you can have two variables with the same name defined in two different modules, and their content will be different. But the module does not really "run" in parallel with the main code or other modules.
    The only communication channel between your program and your modules are variables you pass in your DEFINE_MODULE in main program to instantiate the module. Whatever main program or module writes in these variables, both are updated with new values.[/code]

    A communication channel commonly used for modules is to define a virtual device for the module and send/receive events to/from it. A variable for the virtual device itself is shared as explained by Vincen.

    Fred
  • DHawthorneDHawthorne Posts: 4,584
    Out of sheer habit, I tend to use CALL when a return value isn't needed. I don't think in the end there is much difference, and that CALLs were only included in NetLinx to maintain backwards compatibility with Axcent programs.

    I use modules heavily. There are some quirks involved sometimes, but the benefits outweigh them. For example - a customer wants to add another TV room to another system, but not buy a new master. You can take a complete pre-made TV room program, convert it to a module, and add it to your main system. It now has it's own code space and can be treated independently from your main code, reducing clutter and making it easier to service and upgrade.

    One really big advantage to using a virtual device as an interface to a module is that it can replace a raft of variables, eliminating the need to pass them to the module. Active inputs on a projector? Set a level on the interface virtual. Ditto for screen mode, volume level; channels can reflect power state or cooling/warming. There is just a ton of stuff you can share without having to make convoluted arrays or structures (which you can't passs to a module anyway). In short, it's much closer to real OOP - I only wish they had include a way to access internal module functions, but I suppose that is one of the things Duet is supposedto bring to the table, if it ever really gets off the ground.
  • GSLogicGSLogic Posts: 562
    Modules are just code that get there own tagged variables to keep them apart from all the other variables. It all gets compiled to one program in the end.

    My complaint is most AMX modules don't come with the source code. You only get the .tko file and 9 out of 10 times I will have to rebuild the module because of all the changes from the client or errors in the module. AMX should just included the source code and let us decide if we want to use it. We would also agree not to call tech support in regards to modules that we mutated.
  • I've had the "release TKO" conversation a few times with factory, and the bottom line is that some manufacturers consider their comm protocol proprietary, and so AMX's position is that comm module can not be released other than TKO.

    Bill Ravenel
  • GSLogicGSLogic Posts: 562
    I understand there are companies that consider their comm protocol proprietary, but what a bout the other 90%. The protocol is available and the module would be a nice starting point to build on and would save a lot of time.

    I was told it's because tech support won't be able to support the module (which I agree with) but let the programmer have that option.
  • Joe HebertJoe Hebert Posts: 2,159
    GSLogic wrote:
    ...but what a bout the other 90%. The protocol is available and the module would be a nice starting point to build on and would save a lot of time.

    I was told it's because tech support won't be able to support the module (which I agree with) but let the programmer have that option.

    I second that emotion. Well said.
  • jjamesjjames Posts: 2,908
    How does NetLinx handle a FUNCTION as a parameter in a CALL? Such as:

    CALL 'TUNER ON'(sPRESET(nKP,LAST_RADIO_PRESET[nKP]),PRESET_SEND)

    Where sPRESET is a FUNCTION.
  • DHawthorneDHawthorne Posts: 4,584
    jjames wrote:
    How does NetLinx handle a FUNCTION as a parameter in a CALL? Such as:

    CALL 'TUNER ON'(sPRESET(nKP,LAST_RADIO_PRESET[nKP]),PRESET_SEND)

    Where sPRESET is a FUNCTION.

    As long as the call is expecting a parameter of the same type as the return value of the function, it works just fine. Just be careful if it is expecting an array to send an array, etc. There are cases where a single character (put it in quotes) will be treated like a CHAR array, but might give unexpected results. In your example, as long as the return value of sPRESET is a CHAR[], and the first parameter of 'TUNER ON' is CHAR[], it will work.
Sign In or Register to comment.