Can't START a procedure with a GROUP parameter

c10
Tags: #<Tag:0x00007f60c13f3850>

#1

I’m using Clarion 10 and having a confusing problem. I am trying to START a procedure with a named GROUP as a procedure parameter. The Docs say one can use either a STRING or a GROUP. Here is what I have with XMLGroupType being declared globally.

XMLGroupType GROUP,TYPE
XMLSysID LONG
NewThread BYTE
SuppressCopy BYTE
SuppressFTP BYTE
END

!XMLG is declared locally in the calling procedure.

XMLG GROUP(XMLGroupType)
END

!Here is the prototype of the proc I want to START.
XMLMeetResults PROCEDURE (XMLGroupType pXG)

!Here is my START call. It always generates an error “No matching prototype available”.
START(XMLMeetResults, 25000, XMLG)

I have tried changing the XMLGroupType to a non-TYPE group and using that in the START call rather than the locally declared XMLG but I get the same error. I have also changed it to the following direct call:

XMLMeetResults(XMLG)

and that compiles just fine, no errors.

Can someone point out what I am doing wrong?


#2

The doc is not correct - you should declare your proc as XMLMeetResults(STRING), and pass a group.


#3

Thanks Mike. That appears to be my problem. It’s compiling now and I have another little Clarion oddity to tuck away in the memory banks.


#4

You can only START a procedure with 0,1,2 or 3 STRING arguments
Now, that said, you can do the following.

gtYada GROUP,TYPE
! some fields
       END

MyGroup LIKE(gtYada)
   CODE 
    !.... fill in values in MyGroup 
    START( MyProc,  , ADDRESS( MyGroup) )

MyProc PROCEDURE( STRING xAddressOfMyGroup)
PassedGroup &gtYada
CODE
 PassedGroup &= xAddressOfMyGroup + 0

The same approach works for anything, I often use it for an instance of a class or a queue


#5

Doesn’t seem too safe, unless it’s a class object with its own CS implementation.


#6

It’s safe, as long as you understand what’s shared and what isn’t shared.
often you’ll NEW the class, set the properties and pass it via START.
In that case the class should be DISPOSED by the started procedure when it’s done with it.


#7

but the should here is just convention based on your expected usage. It depends massively on the intent. i.e. you could New up a class and pass it on to something via start which then hands it off somewhere else or whatever and something down the chain knows, based on some other convention, that it is time to clean up. Or you could Notify() the caller and say “Hey, I’m done with this now… re-use the class or cleanup thanks”. etc.

Hey, on a side note… can a class dispose of itself?


#8

Yes, a class can dispose itself. Just don’t try to do anything afterwards.

MyClass.Kill PROCEDURE ()
code
Dispose(self)


#9

Okay, if it’s just a handoff of NEW’d data, that’s cool.

But to pass that address around between threads where they all access it would need to be treated like any other non-threaded global data. (e.g. Critical Section)
And then you’d have to be extra careful if it’s declared data (not NEW’d). If the originating thread closes, the other threads would need to know that their received parameter addresses are now bad.


#10

It works if your instantiation is not declared (e.g. a reference). This, for example, crashes:

 PROGRAM
 MAP
 END

c CLASS !Not a TYPE
Construct PROCEDURE
  END

  CODE

 MESSAGE('Test')

c.Construct PROCEDURE

   CODE
   DISPOSE(SELF)

In addition, if there are any references to that self killed object, they will not know that their referred-to object is NULL.


#11

Neat, so I suppose you could have a class that would stick around for a while but have a kill switch in case someone forgets to clean it up :smiley:


#12

For the guest who has over stayed your welcome.