This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Proxy vs. Calling RTSC Interface Functions from Application Code

Hi,

I’m familiarizing myself with RTSC and curious how the following lines of code (from ti\sdo\ipc\MessageQ.c) work:

    ti_sdo_ipc_MessageQ_Object *obj = (ti_sdo_ipc_MessageQ_Object *)handle;

   ......

    /* Signal the synchronizer */

    ISync_signal(obj->synchronizer);

 

Mainly, the call to ISync_signal() is referencing an interface and is not directly implemented in any “ISync.c” file (as expected for an interface).  The call must eventually get tied to the underlying implementation module that inherits ISync.  Do calls to interface functions only work when the calling code is itself a RTSC module implementation (in this case the MessageQ module)?  Would it be possible to call ISync_signal() or any other interface function from my own .c file if I so desired?

In my application, I have several modules that implement/inherit an interface.  I would like to be able to call a common function regardless of which module I'm using.  I'm not sure if a proxy or a call similar to the one above is the appropriate thing to do.  Here's a summary of my application modules:

IMessageRouting Interface --> defines the SendMessage() function.

InternalMessageRouting and ExternalMessageRouting are two implementations of IMessageRouting.

I have a linked list of IMessageRouting_Handles, some InternalMessageRouting and some ExternalMessageRouting.

In my application, I create a IMessageRouting_Handle variable called currentMessageRouter to iterate through the linked list of IMessageRouting_Handles.

Can I call IMessageRouting_SendMessage( currentMessageRouter) and have the underlying module type known ?  Is a proxy factory required for this?

Thanks,

Nick

  • Nick,
    you are right, the call to ISync_signal() is forwarded to the implementation of ISync through a virtual function table. The instance obj->synchronizer holds a pointer to a table of functions implemented in its module. You don't have to be in a RTSC module to make such a call.

    You don't need proxies either. The purpose of a proxy is to select an implementation of an interface at the config time, and then any reference to the proxy at the runtime always references the configured implementation. Under some circumstances, that's done more efficiently than using virtual tables. Since your table contains handles of both modules, you can't really use proxies because making calls through a proxy would mean that you decided at the config time to use instances of exactly one of those two modules.

  • I'm mainly looking for a way to replicate Interface Primer 15 -> AppFa using static instances of the different interface implementations rather than dynamic.  Would an array of interface handles be sufficient in this case? 

    For example: if I create an array IMessageRouting_Handle routing_list[ ] in the .cfg or in some RTSC module where each element is either an InternalMessageRouting or ExternalMessageRouting handle.  Then can I call IMessageRouting_SendMessage(routing_list[x]) and have the underlying implementation be known ?

  • I just saw a note for Interface Primer 15:

    NOTE:  This lesson leverages some new proxy capabilities slated for XDCtools 3.30.
    NOTE:  For now, just treat the programming examples as "read-only".

    If my above post will not work, any word on when XDCtools 3.30 will be available?

  • Nick,
    you can achieve what you were trying to do without instance factories. Here is an example in terms of number generators used in Interface Primer. I already explained in my previous post that we have something that looks just like basic C++ polymorphism. The harder part is to create an array of handles of different modules. You have to use $add to add elements to the array. This should get you going, please let me know if you need more help.

    var AppFa = xdc.useModule('bravo.math2.genapps.AppFa');
    var Program = xdc.useModule('xdc.cfg.Program');
    var SineGen = xdc.useModule('bravo.math2.SineGen');
    var RandGen = xdc.useModule('bravo.math2.RandGen');

    AppFa.genTab.$add(RandGen.create());
    AppFa.genTab.$add(SineGen.create());

    Program.main = AppFa.main;

    Here, you are creating an array of IGen handles and adding them to genTab array defined in AppFa.xdc:

    import stdsorg.math.IGen;

    /*! IGen app using factory-created instances */
    module AppFa {

        config IGen.Handle genTab[];

        /*! Program entry point */
        Int main(Int argc, Char* argv[]);
    }

    Finally, here is the app code:

    #include <xdc/runtime/System.h>
    #include <stdsorg/math/IGen.h>
    #include "package/internal/AppFa.xdc.h"

    Int AppFa_main(Int argc, Char* argv[]) {
        int i;
        for (i = 0; i < 2; i++) {
            System_printf("%d ", IGen_next(AppFa_genTab[i]));
        }
        System_printf("\n");
        return 0;
    }

  • I believe I accomplished the same using the following format for my .cfg file:

    var RandGenInst = RandGen.create();

    var SineGenInst = SineGen.create();

    AppFa.genTab = [RandGenInst, SineGenInst];

     

    I should be able to reference that example project from here.

    Thanks!