Var_stat

2017-02-21
2017-02-23
  • josepmariarams - 2017-02-21

    Dears.

    I have test to access a var_stat variable using class name as the path to the variable:

    ClassName.variable

    But the compiler tell me that the class had to be instantiated.

    It is possible in Java.

    I am doing something wrong?

    Will it be possible in future?

    It would help me to implement an instanceof function.

     
  • camferti - 2017-02-21

    Lo has probado?

    Enviado desde mi SM-G930F mediante Tapatalk

     
  • Joan M - 2017-02-21

    Have not tried it... What you suggest would be very interesting though.

    A way to get what you want would be using an interface that should be implemented in all your function blocks. Then the interface should have a method or variable that would return what you are interested.

    Hope this helps.

     
  • josepmariarams - 2017-02-21

    All my classes have an string attribute with the class name

    Nowadays i made the class text comparing string:

    Isinstanceof(pointer,'class_name')

    But i dont like it. If i put an wrong string... It will return false.

    If i could pass something related with the class :

    Classname.var

    I will have not error strings

     
  • Joan M - 2017-02-21

    Hi again Josep M,

    Wouldn't this help you?

    Both are examples from the SoMachine help system:

    QUERYINTERFACE ==>

    INTERFACE ItfBase EXTENDS __System.IQueryInterface
    METHOD mbase : BOOL
    END_METHOD
    /////////////////////////////////////////////////////////////////////
    INTERFACE ItfDerived1 EXTENDS ItfBase
    METHOD mderived1 : BOOL
    END_METHOD
    /////////////////////////////////////////////////////////////////////
    INTERFACE ItfDerived2 EXTENDS ItfBase
    METHOD mderived2 : BOOL
    END_METHOD
    /////////////////////////////////////////////////////////////////////
    PROGRAMM POU
    VAR
      itfderived1 : ItfDerived1;
      itfderived2 : ItfDerived2;
      bTest1, bTest2, xResult1, xResult2: BOOL;
    END_VAR
    xResult1 := __QUERYINTERFACE(itfbase, itfderived1); // variablen vom Type ItfBase bzw ItfDerived1
    xResult2 := __QUERYINTERFACE(itfbase, itfderived2); // variablen vom Type ItfBase bzw ItfDerived2
    IF (xResult1 = TRUE) THEN
      bTest1 := itfderived1.mderived1();
    ELSIF xResult2 THEN
      bTest2 := itfderived2.mderived2();
    END_IF
    

    QUERYPOINTER ==>

    INTERFACE Itf EXTENDS __System.IQueryInterface
    /////////////////////////////////////////////////////////////////////
    FUNCTION_BLOCK FBVariant IMPLEMENTS ITF
    METHOD m1 : BOOL
    VAR
    END_VAR
      m1 := TRUE;
    END_METHOD
    /////////////////////////////////////////////////////////////////////
    PROGRAMM POU
    VAR
      itf1 : Itf;
      insV : FBVariant;
      xResult, xTest : BOOL;
      pVar: POINTER TO FBVariant;
    END_VAR
    itf1 := insV;
    xResult := __QUERYPOINTER(itf1, pVar);
    IF xResult THEN
      xTest := pVar.m1();
    END_IF
    

    This is similar to the IsKindOf...

    Hope this helps...

     
  • josepmariarams - 2017-02-22

    Joan

    I am sorry, i have read dozens of times querypointer and i cannot find its sense.

    One posible solution that I found is use __crc. It accepts this, super and class definition.

    I could save crc of an instance on fb init in an internal variable

    Mycrc=__crc(this)

    Instanceof(pobj:=object,crcclass:=__crc(class))

    If (pobj.mycrc=crcclass)return true

     
  • Joan M - 2017-02-22

    If I've not misunderstood your post with the Iskindof...

    You are getting exactly that:

    You have a function block instance: FBI.
    You have an interface itf.
    You have a pointer to check if it's of the same kind than FBI.

    You are getting true if the pointer is of the same kind than FBI.

    function IsKindOfFBI(ptr) : BOOL
    var
    {
      itf : itfG;
      fb : FBI;
    }
    code
    {
      itf := fb;
      IsKindOfFBI := __QUERYPOINTER(itf, ptr);
    }
    

    Am I wrong?

    PS: that is pseudo - code at best, I've not tested it.

    If this works, you could put it into a method in all your fb's and then:

    method IsKindOf(ptr) : BOOL
    var
    {
      itf : itfG;
    }
    code
    {
      itf := this^;
      IsKindOf := __QUERYPOINTER(itf, ptr);
    }
    

    Hope this helps.

     
  • rickj - 2017-02-22

    Joseph,

    As I understand VAR_STAT variables are only visible from within instances of the function block where they are defined. There is only a single instance of a VAR_STAT variable regardless the number of function block instances. It's the same as a class variable except it's only accessible from within a class instance (i.e. function block).

     
  • josepmariarams - 2017-02-23

    Dears:

    For that I have to do I need a function with two inputs : The instance to test and a model to test with.

    The problem comes with the model to test, options that I could find:

    option A: Use var_stat variable. But :
    It is not possible to acces an var_stat via Classname.varstat.
    I have test to access externally an var_stat variable via an undimensioned pointer and It works. (not modifying it only reading it)

    Option B: Use as model test __CRC(nameClass). It works.

    Option C: As Joan says using QUERYPOINTER.

    QUERYINTERFACE has the same mission and works testing if an FB or interface impelments another interface. Is that I need but it works with interfaces and I need that it works with inherited classes.

    QUERYPOINTER is the other solution. But in my CODESYS version don't make the test simply makes a cast. Another question is that I have see 2 pdfs with diferent information.

    One from Codesys:
    Another from Lenze:

    Codesys sasy that you have to test the instance explicitly. And Lenze says that you could cast to any kind of pointer and transforms it ????

    And in the other hand Joan show me another examble from Beckoff wich explains another thing.

    Obviously Joan otions is the better but I have test it and allways returns true.

    PLC Designer__PLC Designer (R3 1)__v4 1__EN.pdf [31.91 KiB]

    OOP_in_CODESYS_3_en.pdf [155.54 KiB]

    OOP_in_CODESYS_3_en.pdf [155.54 KiB]

    PLC Designer__PLC Designer (R3 1)__v4 1__EN.pdf [31.91 KiB]

     
  • Joan M - 2017-02-23

    Hi Josep,

    Time ago I read the Codesys PDF you have just posted.

    This is unclear, and too short in explanations. And lead me to error.

    QueryPointer in Schneider help: agrees with lenze.
    QueryPointer in Beckhoff help: agrees with lenze too.

    So Querypointer is to get the pointer to the interface and be able to keep working from there. Interesting but not what you are after...

    But... after re-reading the Codesys PDF... It looks like the QueryInterface could be used to do what you are after... here I'm pasting an example of queryinterface from Schneider:

    Example in ST: 
    INTERFACE ItfBase EXTENDS __System.IQueryInterface
    METHOD mbase : BOOL
    END_METHOD
    INTERFACE ItfDerived1 EXTENDS ItfBase
    METHOD mderived1 : BOOL
    END_METHOD
    INTERFACE ItfDerived2 EXTENDS ItfBase
    METHOD mderived2 : BOOL
    END_METHOD
    FUNCTION_BLOCK FB1 IMPLEMENTS ItfDerived1
    METHOD mbase : BOOL 
        mbase := TRUE;
    END_METHOD 
    METHOD mderived1 : BOOL 
        mderived1 := TRUE;
    END_METHOD 
    END_FUNCTION_BLOCK
    FUNCTION_BLOCK FB2 IMPLEMENTS ItfDerived2
    METHOD mbase : BOOL 
        mbase := FALSE;
    END_METHOD 
    METHOD mderived2 : BOOL 
        mderived2 := TRUE;
    END_METHOD 
    END_FUNCTION_BLOCK
    PROGRAM POU
    VAR
        inst1 : FB1;
        inst2 : FB2;
        itfbase1 : ItfBase := inst1;
        itfbase2 : ItfBase := inst2;
        itfderived1 : ItfDerived1 := 0;
        itfderived2 : ItfDerived2 := 0;
        bTest1, bTest2, xResult1, xResult2: BOOL;
    END_VAR
    xResult1 := __QUERYINTERFACE(itfbase1, itfderived1); // xResult = TRUE, itfderived1 <> 0
                                          // references the instance inst1
    xResult2 := __QUERYINTERFACE(itfbase1, itfderived2); // xResult = FALSE, itfderived2 = 0
    xResult3 := __QUERYINTERFACE(itfbase2, itfderived1); // xResult = FALSE, itfderived1 = 0
    xResult4 := __QUERYINTERFACE(itfbase2, itfderived2); // xResult = TRUE, itfderived2 <> 0
                                          // references the instance inst2
    

    See at the end when do the __QeryInterface calls fail and when it succeeds... it looks like that it transforms only if the types are equal.

    Hope this helps Josep (and sorry for the initial mistake).

     

Log in to post a comment.