Double Parens

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Double Parens

Scott
I have a simple VB class named HSEvent defined as below

Dim hs As HomeSeer.Application
Public Event HomeSeerEvent(parms As Variant)
Private Sub Class_Initialize()
    Set hs = CreateObject("homeseer.Application")
    hs.RegisterEventCB 255, Me
End Sub
Public Sub HsEvent(parms As Variant)
    RaiseEvent HomeSeerEvent((parms))
End Sub
Private Sub Class_Terminate()
    Set hs = Nothing
End Sub

When I use an EventSink connected to HSEvent (event HomeSeerEvent) in
Dolphin, I get 'parms' into dolphin as a Variant with a SafeArray of
values (integers and strings).  But when this line
    RaiseEvent HomeSeerEvent((parms))
is changed to
    RaiseEvent HomeSeerEvent(parms)
I get 'parms' into dolphin as a Variant pointing to a LPVoid.  

How can I dublicate in Dolphin Smalltalk to what happens in VB with
the double parens.  I am trying to remove the VB portion of the code
and do it all in Dolphin Smalltalk

Thanks,
Scott.


Reply | Threaded
Open this post in threaded view
|

Re: Double Parens

Blair McGlashan
Scott

"Scott" <[hidden email]> wrote in message
news:[hidden email]...

> I have a simple VB class named HSEvent defined as below
> [...
> Dim hs As HomeSeer.Application
> Public Event HomeSeerEvent(parms As Variant)
>...[snip]...
>
> When I use an EventSink connected to HSEvent (event HomeSeerEvent) in
> Dolphin, I get 'parms' into dolphin as a Variant with a SafeArray of
> values (integers and strings).  But when this line
>     RaiseEvent HomeSeerEvent((parms))
> is changed to
>     RaiseEvent HomeSeerEvent(parms)
> I get 'parms' into dolphin as a Variant pointing to a LPVoid.
>
> How can I dublicate in Dolphin Smalltalk to what happens in VB with
> the double parens.  I am trying to remove the VB portion of the code
> and do it all in Dolphin Smalltalk

The "Event" is declared as taking a variant parameter. When you invoke a
function/method taking a variant parameter in Dolphin the high-level wrapper
method generated by Dolphin's type-library analyzer will send #asVariant to
all the Smalltalk Objects passed to it, forwarding the results to the
low-level wrapper method. The #asVariant conversion for Therefore to get a
SAFEARRAY of VARIANT passed, you need to pass in a Collection of Objects,
i.e. instead of:

self raiseHomeSeerEvent: 'Hello'

you might say:

self raiseHomeSeerEvent: (Array with: 'Hello')

However I'm not quite sure if this is what you are asking. I presume you are
trying to directly implement this control's custom callback/event mechanism
in Dolphin, which is certainly possible, in which case what one would need
to know is: What form does 'parms' have on entry to the HsEvent method? What
does the documentation for the control say it should be? With that
information available it should be possible to convert it.

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: Double Parens

Scott
This HomeSeer application has it own callback event system where you
pass in an object that has a public method named HSEvent (parms as
variant) and this will be called by HomeSeer.  So I am trying to
create a COM Server (I have generated and compiled IDL that is the
same as the VB code sample (different GUIDs)) in Dolphin and the
HSEvent is getting called from HomeSeer, but the parms is a Variant
pointing to a LPVoid.

I am trying to figure out why the VB code with double parens work, so
I can try to the same thing in Smalltalk.

The following is some documentation about the callback feature of
HomeSeer:

"You can call into HomeSeer and register a form object that will be
called when HomeSeer receives an X10 command. Call the following
function:

hs.RegisterEventCB evtype as long, obj as object

The evtype parameter is a bitmap of event types. The event types are
defined as follows:
const ev_type_x10 = 1 ' X10 received event
const ev_type_log = 2 ' a message written to the event log

The obj parameter should be a reference to a form with the following
method declared public:
Public Sub HSEvent(parms as variant)
End Sub

The parameters are passed in a variant that is an array of variants.
Each entry in the array is a parameter. The number of entries depends
on the type of event and are described below.  The event type is
always present in the first entry or parms(0). The parms(0) event type
is defined as follows:
1 = X10 event
2 = Event log message event

Parameters for the X10 event:
parms(1)=devices = [device string like "A1+2"]
parms(2)=housecode = [the houscode the command was heard on like "A"]
parms(3)=command = [the actual X10 command, in the range 1 -> 16]
parms(4)=dim_level = [normally the dim level from a dim command, or
data byte 1
for the extended X10 command]
parms(5)=data2 = [data byte 2 for the extended X10 command]

Parameters for the event log event are:
parms(1)=date_time = [date and time of log entry]
parms(2)=msg_class = [type of log entry, ie: "speak" or "ERROR", etc]
parms(3)=msg = [the actual event log message]

Other events may be added in the future.

HomeSeer will then call the HSEvent method when the requested event is
available."



"Blair McGlashan" <[hidden email]> wrote in message news:<a0ulcu$n2od6$[hidden email]>...

> Scott
>
> "Scott" <[hidden email]> wrote in message
> news:[hidden email]...
> > I have a simple VB class named HSEvent defined as below
> > [...
> > Dim hs As HomeSeer.Application
> > Public Event HomeSeerEvent(parms As Variant)
> >...[snip]...
> >
> > When I use an EventSink connected to HSEvent (event HomeSeerEvent) in
> > Dolphin, I get 'parms' into dolphin as a Variant with a SafeArray of
> > values (integers and strings).  But when this line
> >     RaiseEvent HomeSeerEvent((parms))
> > is changed to
> >     RaiseEvent HomeSeerEvent(parms)
> > I get 'parms' into dolphin as a Variant pointing to a LPVoid.
> >
> > How can I dublicate in Dolphin Smalltalk to what happens in VB with
> > the double parens.  I am trying to remove the VB portion of the code
> > and do it all in Dolphin Smalltalk
>
> The "Event" is declared as taking a variant parameter. When you invoke a
> function/method taking a variant parameter in Dolphin the high-level wrapper
> method generated by Dolphin's type-library analyzer will send #asVariant to
> all the Smalltalk Objects passed to it, forwarding the results to the
> low-level wrapper method. The #asVariant conversion for Therefore to get a
> SAFEARRAY of VARIANT passed, you need to pass in a Collection of Objects,
> i.e. instead of:
>
> self raiseHomeSeerEvent: 'Hello'
>
> you might say:
>
> self raiseHomeSeerEvent: (Array with: 'Hello')
>
> However I'm not quite sure if this is what you are asking. I presume you are
> trying to directly implement this control's custom callback/event mechanism
> in Dolphin, which is certainly possible, in which case what one would need
> to know is: What form does 'parms' have on entry to the HsEvent method? What
> does the documentation for the control say it should be? With that
> information available it should be possible to convert it.
>
> Regards
>
> Blair


Reply | Threaded
Open this post in threaded view
|

Re: Double Parens

Blair McGlashan
Scott

You wrote in message news:[hidden email]...
> This HomeSeer application has it own callback event system where you
> pass in an object that has a public method named HSEvent (parms as
> variant) and this will be called by HomeSeer.  So I am trying to
> create a COM Server (I have generated and compiled IDL that is the
> same as the VB code sample (different GUIDs)) in Dolphin and the
> HSEvent is getting called from HomeSeer, but the parms is a Variant
> pointing to a LPVoid.
>...

OK, so tell us a bit more about that VARIANT. What is its 'vt'? (VARIANT is
a discrimnated union with the 'vt' member holding the type of data stored in
the union). Based on the HomeSeer docs you quoted I would have expected it
to be (VT_ARRAY|VT_VARIANT) (i.e. 8204). Basically you need to investigate
what the VARIANT actually contains. If it actually contains a
(VT_BYREF|VT_ARRAY|VT_VARIANT), then I think that might explain what you are
seeing. Try evaluating (in the debugger at a breakpoint in the HSEvent
callback method):

    SAFEARRAY fromAddress: parms refAddress vt: VT_VARIANT owner: parms

This might work (please let me know if it does), but be very careful about
the lifetime of the SAFEARRAY; it is being passed by referenced and will
probably disappear as soon as HSEvent returns. If you need to capture it,
then #copy it, or translate it into a Smalltalk collection immediately.

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: Double Parens

Scott
> OK, so tell us a bit more about that VARIANT. What is its 'vt'? (VARIANT is
> a discrimnated union with the 'vt' member holding the type of data stored in
> the union). Based on the HomeSeer docs you quoted I would have expected it
> to be (VT_ARRAY|VT_VARIANT) (i.e. 8204). Basically you need to investigate
> what the VARIANT actually contains. If it actually contains a
> (VT_BYREF|VT_ARRAY|VT_VARIANT), then I think that might explain what you are
> seeing.

parms isByRef answers true. the 'vt' member is 24588 (which I believe
is (VT_BYREF|VT_ARRAY|VT_VARIANT)).

> Try evaluating (in the debugger at a breakpoint in the HSEvent
> callback method):
>
>     SAFEARRAY fromAddress: parms refAddress vt: VT_VARIANT owner: parms

This did not work for me. The printString of the answer shows 'an
invalid SAFEARRAY'

Any other suggestions on how to get the values?

Thanks,
Scott


Reply | Threaded
Open this post in threaded view
|

Re: Double Parens

Blair McGlashan
Scott

You wrote in message news:[hidden email]...
> > OK, so tell us a bit more about that VARIANT. What is its 'vt'? (VARIANT
is
> > a discrimnated union with the 'vt' member holding the type of data
stored in
> > the union). Based on the HomeSeer docs you quoted I would have expected
it
> > to be (VT_ARRAY|VT_VARIANT) (i.e. 8204). Basically you need to
investigate
> > what the VARIANT actually contains. If it actually contains a
> > (VT_BYREF|VT_ARRAY|VT_VARIANT), then I think that might explain what you
are
> > seeing.
>
> parms isByRef answers true. the 'vt' member is 24588 (which I believe
> is (VT_BYREF|VT_ARRAY|VT_VARIANT)).

Yup.

>
> > Try evaluating (in the debugger at a breakpoint in the HSEvent
> > callback method):
> >
> >     SAFEARRAY fromAddress: parms refAddress vt: VT_VARIANT owner: parms
>
> This did not work for me. The printString of the answer shows 'an
> invalid SAFEARRAY'

The debugger and inspector suppress errors that occur printing things as
otherwise walkbacks would pop-up all over the place when debugging. You can
debug the actual printing though, e.g. <expression> printString "Ctrl+E",
then debug from the resulting walkback.

>
> Any other suggestions on how to get the values?

Not really. I would have expected that to do it for that 'vt' type. I was
going to suggest the attached modification to the VARIANT class, but it
amounts to effectively the same thing. Nevertheless you may want to try it.

Regards

Blair
-------------------------

!VARIANT methodsFor!

array
 "Answer a SAFEARRAY from the receiver.
 Assumes that the receiver actually references an array."

 ^SAFEARRAY
  fromAddress: (self isByRef ifTrue: [self refAddress] ifFalse: [self
ulVal])
  vt: self vartype
  owner: self! !
!VARIANT categoriesFor: #array!accessing!public! !


Reply | Threaded
Open this post in threaded view
|

Re: Double Parens

Scott
I will give this a try tonight when I get home.  Is there any way of
changing the IDL of HSEvent so that it does NOT pass byRef (pass by
value instead)?

Thanks,
Scott

Following is the IDL that I compiled:
(This was copied (GUIDs where changed) from the working VB code that
with the Double Parens passed Variant(SafeArray), Single Paren passed
Variant(LPVoid))
"should the parms be [in, out]? "
"should the parms be VARIANT instead of VARIANT*?"

[
  uuid(3144380B-2FB7-4078-8E2C-310A5BC12017),
  version(1.0),
  helpstring("HomeSeer Event Dispatcher")
]
library HomeseerEvent
{
    // TLib :     // TLib : OLE Automation :
{00020430-0000-0000-C000-000000000046}
    importlib("stdole2.tlb");

    // Forward declare all types defined in this typelib
    interface _Application;
    dispinterface __Application;

    [
      odl,
      uuid(90F6E5A3-C82D-4795-814B-7A3E522241F2),
      version(1.0),
      hidden,
      dual,
      nonextensible,
      oleautomation
    ]
    interface _Application : IDispatch {
        [id(0x60030001)]
        HRESULT HsEvent([in, out] VARIANT* parms);
    };

    [
      uuid(D05C182D-8E60-4992-837C-6D6F1DEF8A30),
      version(1.0)
    ]
    coclass Application {
        [default] interface _Application;
        [default, source] dispinterface __Application;
    };

    [
      uuid(31DB7E43-92E8-4bd2-B259-85970913D0B7),
      version(1.0),
      hidden,
      nonextensible
    ]
    dispinterface __Application {
        properties:
        methods:
            [id(0x00000001)]
            void HomeSeerEvent([in, out] VARIANT* parms);
    };


Reply | Threaded
Open this post in threaded view
|

Re: Double Parens

Blair McGlashan
Scott

You wrote in message news:[hidden email]...
> I will give this a try tonight when I get home.  Is there any way of
> changing the IDL of HSEvent so that it does NOT pass byRef (pass by
> value instead)?

No, at least I don't think so, not in isolation (the '[in,out] VARIANT*'
parameter should be '[in] VARIANT'). The code that invokes HSEvent would
need to be changed as well I think, but you could try it.

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: Double Parens

Scott
I change the IDL for parms to be '[in] VARIANT' and that did not work
either.  Nor did the VARIANT>>array method changes help.

Any other suggestions?

Scott


Reply | Threaded
Open this post in threaded view
|

Re: Double Parens

Scott
The following is an answer for my question about what an extra set of
parens does in VB.  Is it possible to do something in Smalltalk or the
IDL to do the same thing?

Thanks,
Scott

<reply>
I'm not sure how it applies to your specific situation here... but
speaking in general about VB, putting a parameter in an extra set of
parens forces the parameter to be evaluated and thus passed by value.
The same can be accomplished for all calls to a function with the
ByVal keyword.
To put that another way, if MyVar has been set to 5 and you execute
Call MyFunction(MyVar), what's passed to MyFunction is not 5, but
MyVar itself. Thus, if you want, MyFunction can make changes to the
value it gets, and those changes will actually happen to MyVar.

But (MyVar) isn't MyVar; it's an expression whose value is 5, just
like (MyVar+1) is an expression whose value is 6. When you pass
(MyVar) in, all that gets passed in is the value 5, and thus,
MyFunction can change it all it wants without affecting MyVar.

If you declare MyFunction with a ByVal parameter, that accomplishes
the same thing as the extra parens, only to all calls to MyFunction.

When a variable is actually a structure or pointer, this same concept
can also cause changes to types, because when something like this is
passed in by reference, all that gets passed is a pointer, because
that's all you need. That way, changes are happening back in the
original variable. But when it gets passed in by value, a complete
copy of the original structure is sent in, so changes will happen to
the copy. This usually is transparent, but when you hop languages the
difference can be significant. I think that's what you're seeing.
</reply>