Announcement

Collapse
No announcement yet.

LET objvar = NOTHING ... does nothing?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • LET objvar = NOTHING ... does nothing?

    I am using a 3rd party COM control (see: 3rd Party COM not working with PB9 for more info) and when you set its .address property is connects to a controller at the specified IP address.

    However in there documentation is says when the object reaches the end of its scope it will disconnect. Well there are cases where I may want to disconnect before reaching the end of the scope being that the object is a global.

    So I was reading through PB9 documentation it says setting the object to NOTHING will handle that, or at least that's what I got from it. Well it sets the object to nothing, but it does not seem that the deconstructor for this object is executed at this time.

    If I close the software I disconnect just fine from the controller. However if I set the object to NOTHING I still stay connected to the controller until I close the software.

    Any ideas?
    Thank you,
    Ryan M. Cross

  • #2
    Ryan,
    It's not just you. I am getting the same sort of things from VB calling my PB COM dll. Where it will either call the destructor 1 time too few or 1 time too many and cause a crash.

    I am looking into a safer way to do it, but have not come up with anything yet.
    Engineer's Motto: If it aint broke take it apart and fix it

    "If at 1st you don't succeed... call it version 1.0"

    "Half of Programming is coding"....."The other 90% is DEBUGGING"

    "Document my code????" .... "WHYYY??? do you think they call it CODE? "

    Comment


    • #3
      A destructor is only called when the reference count for an object reaches zero. If you have any copies of this object instantiated then the reference count is not zero and the destructor will not be called until all copies of the object are set to nothing. This maybe why when you close the application all instances of the object are destoyed and the destructor is called.
      Sincerely,

      Steve Rossell
      PowerBASIC Staff

      Comment


      • #4
        If by "disconnect" you mean the COM DLL being unloaded, you will need to call CoFreeUnusedLibraries.
        Forum: http://www.jose.it-berater.org/smfforum/index.php

        Comment


        • #5
          Well I made test program because I wanted to see if the Galil COM object would disconnect from the server after a thread that used locals instead of a global.

          What I found is when the thread gets to the end it crashes the program, unless I put a MsgBox at the end of the thread. Weird I know, I'm not sure if this is a PowerBasic issue or an issue with the COM.

          Another thing I noticed was if I do not use events for the object I have no problems, so I believe its something related to the events. It disconnects as expected with no events, but crashes with them even though I attempt to stop them before the end of the thread. Here's the exact code:

          Code:
          #COMPILE EXE
          
          #INCLUDE "Galil.inc"
          
          global Thread1Running as long
          global Galil1Connected as long
          
          function pbmain()
          	local hThread as long
          
          	'Create Thread
          	THREAD CREATE CreateGalil(0) TO hThread
          	
          	'Loop until Galil1Connected = 1
          	do
          		sleep 10
          	loop until Galil1Connected
          	
          	'Yes we have connected!
          	msgbox "Connected! Click okay to disconnect."
          	
          	'Start disconnection
          	Thread1Running = 0
          	
          	'Loop until Galil1Connected = 0
          	do
          		sleep 10
          	loop until isfalse(Galil1Connected)
          	
          	'Yes we have disconnected!
          	msgbox "Disconnected."
          
          end function
          
          thread function CreateGalil(byval x as long) as LONG
          	local GalilCont as IGalil, GalilContEvents as IGalil_Events, IP as string
          	
          	'Thread is running
          	Thread1Running = 1
          	
          	let GalilCont = NEWCOM CLSID $CLSID_Galil
          	
          	GalilContEvents = CLASS "Class_IGalil_Events"
          	
          	EVENTS FROM GalilCont CALL GalilContEvents '<- Commenting out this line prevents it from crashing, however I obviously do not receive any events
          	
          	IP = ucode$("192.168.1.151")
          	
          	OBJECT LET GalilCont.address = IP
          	
          	'Galil is connected
          	Galil1Connected = 1
          	
          	'Loop until Thread1Running is set to 0
          	do
          		sleep 10
          	loop until isfalse(Thread1Running)
          
          	'Stop events
          	EVENTS end GalilContEvents
          	
          	'Set events to nothing
          	let GalilContEvents = nothing
          	
          	'Set COM to nothing
          	let GalilCont = nothing
          
          	Galil1Connected = 0
          	
          	'msgbox "This MsgBox here prevents it from crashing, if I comment it out it will crash"
          	
          	'This is where the crash occurs
          end function
          
          Class Class_IGalil_Events $CLSID_Event_Events As Event
          	
          	Interface IGalil_Events $IID_Int_Events '<- Commenting out "$IID_Int_Events" also prevents it from crashing, however I obviously do not receive any events
          		Inherit IDispatch
          
          		Method onInterrupt <0> (Byval PB_status As Long)
          
          		End Method
          
          		Method onMessage <1> (Byval message As String)
          
          		End Method
          
          		Method onRecord <2> (Byval record As Variant)
          		
          		End Method
          
          	End Interface
          	
          End Class
          Last edited by RyanCross; 30 Oct 2008, 02:21 PM.
          Thank you,
          Ryan M. Cross

          Comment


          • #6
            Originally posted by José Roca View Post
            If by "disconnect" you mean the COM DLL being unloaded, you will need to call CoFreeUnusedLibraries.
            No I mean disconnect like the COM object disconnecting from the controller.
            Thank you,
            Ryan M. Cross

            Comment


            • #7
              Ryan, I get the same sort of thing from a VB point of view, that when I set the variable = nothing then I crash. (But only if my variable involves Events)

              If the variable only uses properties and methods and not events then all is fine.....So its a bit of a conundrum to me
              Engineer's Motto: If it aint broke take it apart and fix it

              "If at 1st you don't succeed... call it version 1.0"

              "Half of Programming is coding"....."The other 90% is DEBUGGING"

              "Document my code????" .... "WHYYY??? do you think they call it CODE? "

              Comment


              • #8
                You are creating the instance of the object in a thread, but you aren't calling CoInitialize. See: http://msdn.microsoft.com/en-us/magazine/cc302324.aspx
                Forum: http://www.jose.it-berater.org/smfforum/index.php

                Comment


                • #9
                  Jose,
                  Just to simplify things, lets say I was doing the same from VB to a PB port of the code to the DLL.

                  With COM would that mean that my "Parent Program / Main Thread" would be one thing, and each object I create from there would be "A new Thread" sort of thought???

                  If that is the case then another post you put somewhere was
                  CoInitializeEx and CoUninitialize
                  and how PB handles that normally, but would that be only for my "Parent" app, and each object I create I in turn have to handle the CoInitializeEx and CoUninitialize???
                  Sorry if confusing, but I am trying to bridge in my mind what works fine as a PB solution only vs creating a DLL to be used with other programs/languages.
                  Engineer's Motto: If it aint broke take it apart and fix it

                  "If at 1st you don't succeed... call it version 1.0"

                  "Half of Programming is coding"....."The other 90% is DEBUGGING"

                  "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                  Comment


                  • #10
                    and how PB handles that normally, but would that be only for my "Parent" app, and each object I create I in turn have to handle the CoInitializeEx and CoUninitialize???
                    I don't understand what you mean. PB calls CoInitialize and CoUninitialize under the hood for the main thread of your application. You don't have to call it again to create objects in the main thread. But the above code is creating a new object in another thread, so according to M$ documentation it must call CoInitialize at the start of the thread, that places the thread inside an apartment and initializes important per-thread state information that is required for COM to operate properly, and call CoUninitialize at the end of the thread. And to share object variables between threads, you must marshal them using CoMarshalInterThreadInterfaceInStream and CoGetInterfaceAndReleaseStream.
                    Forum: http://www.jose.it-berater.org/smfforum/index.php

                    Comment


                    • #11
                      CoInitialize & CoUninitialize didn't do anything. Still crashed as a thread. Here is the code:

                      Code:
                      #COMPILE EXE
                      
                      #INCLUDE "Galil.inc"
                      
                      Declare Function CoInitialize Lib "ole32.dll" Alias "CoInitialize" (ByVal pvReserved As Dword) As Dword
                      Declare Sub CoUninitialize Lib "ole32.dll" Alias "CoUninitialize"
                      
                      global Thread1Running as long
                      global Galil1Connected as long
                      
                      function pbmain()
                      	local hThread as long
                      
                      	'Create Thread
                      	THREAD CREATE CreateGalil(0) TO hThread
                      	
                      	'Loop until Galil1Connected = 1
                      	do
                      		sleep 10
                      	loop until Galil1Connected
                      	
                      	'Yes we have connected!
                      	msgbox "Connected! Click okay to disconnect."
                      	
                      	'Start disconnection
                      	Thread1Running = 0
                      	
                      	'Loop until Galil1Connected = 0
                      	do
                      		sleep 10
                      	loop until isfalse(Galil1Connected)
                      	
                      	'Yes we have disconnected!
                      	msgbox "Disconnected."
                      
                      end function
                      
                      thread function CreateGalil(byval x as long) as LONG
                      	local GalilCont as IGalil, GalilContEvents as IGalil_Events, IP as string
                      	
                      	CoInitialize 0
                      	
                      	'Thread is running
                      	Thread1Running = 1
                      	
                      	let GalilCont = NEWCOM CLSID $CLSID_Galil
                      	
                      	GalilContEvents = CLASS "Class_IGalil_Events"
                      	
                      	EVENTS FROM GalilCont CALL GalilContEvents '<- Commenting out this line prevents it from crashing, however I obviously do not receive any events
                      	
                      	IP = ucode$("192.168.1.151")
                      	
                      	OBJECT LET GalilCont.address = IP
                      	
                      	'Galil is connected
                      	Galil1Connected = 1
                      	
                      	'Loop until Thread1Running is set to 0
                      	do
                      		sleep 10
                      	loop until isfalse(Thread1Running)
                      
                      	'Stop events
                      	EVENTS end GalilContEvents
                      	
                      	'Set events to nothing
                      	let GalilContEvents = nothing
                      	
                      	'Set COM to nothing
                      	let GalilCont = nothing
                      
                      	Galil1Connected = 0
                      	
                      	'msgbox "This MsgBox here prevents it from crashing, if I comment it out it will crash"
                      	
                      	'This is where the crash occurs
                      	
                      	CoUninitialize
                      end function
                      
                      Class Class_IGalil_Events $CLSID_Event_Events As Event
                      	
                      	Interface IGalil_Events $IID_Int_Events '<- Commenting out "$IID_Int_Events" also prevents it from crashing, however I obviously do not receive any events
                      		Inherit IDispatch
                      
                      		Method onInterrupt <0> (Byval PB_status As Long)
                      
                      		End Method
                      
                      		Method onMessage <1> (Byval message As String)
                      
                      		End Method
                      
                      		Method onRecord <2> (Byval record As Variant)
                      		
                      		End Method
                      
                      	End Interface
                      	
                      End Class
                      Like I said if I uncomment the message box at the end of the thread everything works as it should, except there's not reason I should obviously have to put a MsgBox at at the end.

                      Also if I remove anything related to events it works as well.

                      So I tried it without it being a thread and I do not get a crash...however it does not work as it should. It does not disconnect from the controller until after the software shuts down and not when the function has ended. Here is the code:

                      Code:
                      #COMPILE EXE
                      
                      #INCLUDE "Galil.inc"
                      
                      Declare Function CoInitialize Lib "ole32.dll" Alias "CoInitialize" (ByVal pvReserved As Dword) As Dword
                      Declare Sub CoUninitialize Lib "ole32.dll" Alias "CoUninitialize"
                      
                      function pbmain()
                      	local hThread as long
                      
                      	'Create Thread
                      	call CreateGalil(0)
                      	
                      	'Yes we have disconnected!
                      	msgbox "Disconnected."
                      
                      end function
                      
                      function CreateGalil(byval x as long) as LONG
                      	local GalilCont as IGalil, GalilContEvents as IGalil_Events, IP as string
                      	
                      	let GalilCont = NEWCOM CLSID $CLSID_Galil
                      	
                      	GalilContEvents = CLASS "Class_IGalil_Events"
                      	
                      	EVENTS FROM GalilCont CALL GalilContEvents
                      	
                      	IP = ucode$("192.168.1.151")
                      	
                      	OBJECT LET GalilCont.address = IP
                      
                      	'Stop events
                      	EVENTS end GalilContEvents
                      	
                      	'Set events to nothing
                      	let GalilContEvents = nothing
                      	
                      	'Set COM to nothing
                      	let GalilCont = nothing
                      	
                      	'No crash, but I should disconnect from the controller at this time
                      end function
                      
                      Class Class_IGalil_Events $CLSID_Event_Events As Event
                      	
                      	Interface IGalil_Events $IID_Int_Events
                      		Inherit IDispatch
                      
                      		Method onInterrupt <0> (Byval PB_status As Long)
                      
                      		End Method
                      
                      		Method onMessage <1> (Byval message As String)
                      
                      		End Method
                      
                      		Method onRecord <2> (Byval record As Variant)
                      		
                      		End Method
                      
                      	End Interface
                      	
                      End Class
                      It seems something is not be handled as it should with the events or something. Whether its a PB thing, a Galil thing, or a me thing I have no idea.
                      Thank you,
                      Ryan M. Cross

                      Comment


                      • #12
                        Another thing I just found out. I continue to receive events in my event sink even AFTER I call EVENTS END GalilContEvents. Shouldn't this stop events being sent to the event sink? I actually do not stop receiving events until the function ends.
                        Last edited by RyanCross; 31 Oct 2008, 09:14 AM.
                        Thank you,
                        Ryan M. Cross

                        Comment


                        • #13
                          Actually, you don't need to call CoInitialize at all. PowerBASIC 9 does it for you at the start of every thread.

                          Bob Zale
                          PowerBASIC Inc

                          Comment


                          • #14
                            So any idea why EVENTS END GalilContEvents does not stop events?
                            Thank you,
                            Ryan M. Cross

                            Comment

                            Working...
                            X