Page 1 of 1

PRIM_KCOL - Invalid_Cast error

Posted: Thu Jul 06, 2023 8:29 pm
by cesarrafael
Hi All,
This might be a very basic thing, however I was wondering if someone could give me a reason why I get a * *INVALID_CAST error when using this situation:

==CR_FUN1 (Function)

Function Options(*DIRECT)
*
Define Field(#W_text) Type(*CHAR) Length(60)
*MyField is a Alpha 60
*
Define_Com Class(#CR_TST2) Name(#getCollection) Scope(*APPLICATION)
Define_Com Class(#PRIM_KCOL<#STD_STRG #MyField>) Name(#KeyedCollection1) Reference(*DYNAMIC)

#KeyedCollection1 <= #getCollection.Mycoll()

For Each(#Item) In(#KeyedCollection1)
#W_text := #Item.Value
Endfor

Return

== CR_TST2 (reusable part)

Function Options(*DIRECT)
Begin_Com Role(*EXTENDS #PRIM_OBJT) Options(*FINAL)
*
Mthroutine Name(MyColl) Help('Test Invalid Cast') Options(*FINAL)
Define_Map For(*RESULT) Class(#prim_kcol<#STD_STRG #MyField>) Name(#PassCollection) Pass(*BY_REFERENCE)

If_Ref Com(#PassCollection) Is(*NULL)
Set_Ref Com(#PassCollection) To(*CREATE_As #prim_kcol<#STD_STRG #MyField>)
Endif
#PassCollection.RemoveAll

#MyField := 'test1'
#PassCollection<#MyField> := 'Cesartest'
*
Endroutine
*
End_Com

== Error message
Message : Unexpected or unhandled runtime error - Failure( *INVALID_CAST ) ReportedBy( File:X_VarEvaluations Line:24272 )


I've tried several things and always get this error....am I doing something wrong?
Many thanks!

Re: PRIM_KCOL - Invalid_Cast error

Posted: Sat Jul 08, 2023 12:08 am
by dominique
Hi Rafael

As far as I know you can't create instance of a result collection. Hope that will help
Bild000080.jpg
Bild000080.jpg (78.88 KiB) Viewed 19801 times

Code: Select all

Evtroutine Handling(#COM_OWNER.CreateInstance)
#com_self.MyCollIn( #com_self.MyCollGet )
Endroutine
Mthroutine Name(MyCollGet)
Define_Map For(*RESULT) Class(#PRIM_KCOL<#STD_TEXT #STD_NUM>) Name(#Collection) Pass(*BY_REFERENCE)

Define_Com Class(#PRIM_KCOL<#STD_TEXT #STD_NUM>) Name(#KeyedCollectionOut)

#KeyedCollectionOut<1> <= *New #STD_TEXT
#KeyedCollectionOut<1> := "Value 1"

#KeyedCollectionOut<2> <= *New #STD_TEXT
#KeyedCollectionOut<2> := "Value 2"


#Collection <= #KeyedCollectionOut
Endroutine
Mthroutine Name(MyCollIn)
Define_Map For(*INPUT) Class(#PRIM_KCOL<#STD_TEXT #STD_NUM>) Name(#Collection) Pass(*BY_REFERENCE)

Define_Com Class(#PRIM_KCOL<#STD_TEXT #STD_NUM>) Name(#KeyedCollectionIn) Reference(*DYNAMIC)

#KeyedCollectionIn <= #Collection


For Each(#item) In(#KeyedCollectionIn)
Use Builtin(MESSAGE_BOX_ADD) With_Args(#item)
Endfor
Use Builtin(MESSAGE_BOX_Show)
Endroutine

Re: PRIM_KCOL - Invalid_Cast error

Posted: Mon Jul 10, 2023 9:09 pm
by cesarrafael
Hi Dominique,

Many thanks!
Yes, it works if both methodroutine are in the same function/reusable part. However if "MyCollIn" and "MyCollGet" are in separate objects, it crashes with the Invalid_cast error....Any idea why this happens?

Cheers,

Re: PRIM_KCOL - Invalid_Cast error

Posted: Tue Jul 11, 2023 12:08 pm
by BrendanB
Cesar,

not sure if you intentionally misspelt the #STD_STRG instead of #STD_STRNG...

But, why pass the reference at all? you could just make the collection a property of the object.

Call the method, then use the property.

Code: Select all

==CR_FUN1 (Function)

Function Options(*DIRECT)
*
Define Field(#W_text) Type(*CHAR) Length(60)
*MyField is a Alpha 60
*
Define_Com Class(#CR_TST2) Name(#getCollection) Scope(*APPLICATION)

* call method to populate the property
#getCollection.MyColl()

* use the property directly...
For Each(#Item) In(#getCollection.PassCollection)
#W_text := #Item.Value
Endfor

Return

== CR_TST2 (reusable part)

Function Options(*DIRECT)
Begin_Com Role(*EXTENDS #PRIM_OBJT) Options(*FINAL)
*
define_com class(#prim_kcol<#STD_STRNG #MyField>) name(#PassCollection)
define_pty name(PassCollection) get(*REFERENCE #PassCollection)
*
Mthroutine Name(MyColl) Help('Test Invalid Cast') Options(*FINAL)

#PassCollection.RemoveAll

#MyField := 'test1'
#PassCollection<#MyField> := 'Cesartest'
*
Endroutine
*
End_Com

Re: PRIM_KCOL - Invalid_Cast error

Posted: Tue Jul 11, 2023 12:24 pm
by BrendanB
You could even take it 1 step further:

Code: Select all

Function Options(*DIRECT)
Begin_Com Role(*EXTENDS #PRIM_OBJT) Options(*FINAL)
*
Define_Com Class(#prim_kcol<#STD_STRNG #std_desc>) Name(#PassCollection)
Define_Pty Name(PassCollection) Get(*REFERENCE #PassCollection)

Define_Pty Name(KeyedColl) Get(pGetPassCollection)
*

Ptyroutine Name(pGetPassCollection)
Define_Map For(*OUTPUT) Class(#prim_kcol<#STD_STRNG #std_desc>) Name(#Property) Pass(*BY_REFERENCE)

#COM_SELF.MyColl
#Property <= #PassCollection

Endroutine

Mthroutine Name(MyColl) Help('Test Invalid Cast') Options(*FINAL)
* Define_Map For(*RESULT) Class(#prim_kcol<#STD_STRNG #std_desc>) Name(#PassCollection) Pass(*BY_REFERENCE)

* #PassCollection <= (*New #PRIM_KCOL<#STD_STRNG #STD_DESC>)
#PassCollection.RemoveAll

#STD_DESC := 'test1'
#PassCollection<#STD_DESC> := 'Cesartest'
*
Endroutine
*
End_Com

CR_FUN1=======
Function Options(*DIRECT)
*
Define Field(#W_text) Type(*CHAR) Length(60)
* MyField is a Alpha 60
*
Define_Com Class(#CR_TST2) Name(#getCollection) Scope(*APPLICATION)

For Each(#Item) In(#getCollection.KeyedColl)
#W_text := #Item.Value
Endfor

Return

Re: PRIM_KCOL - Invalid_Cast error

Posted: Tue Jul 11, 2023 6:52 pm
by cesarrafael
Hi Brendan,

Many thanks! I actually need to store de keyed collection on my calling function, i.e. I need to call a routine on another program and store it on my calling (initial) program...
But no matter what I do, when I try to pass the keyed collection between routines in differerent objects, I get an *Invalid_cast error!

Cheers,

Re: PRIM_KCOL - Invalid_Cast error

Posted: Sat Jul 15, 2023 2:38 am
by jonno
I am also having the same issue although a slightly different scenario namely:
server module method prim_kcol <= RP method prim_kcol
Note: we have it working on the web e.g, web page method <= RP method and also array collections work fine
I tried the suggestion of using a property routine but after a quick try that failed with the same error "invalid_cast", will look again in more detail.
LANSA support response was "the explanation is that this was an unavoidable restriction related to the way that LANSA generates the C++ Code.
The solution is to wrap the keyed collection into a reusable part, and then pass that around instead."