Posted by HMC in SWF Studio V3 on May 15 2008, 08:54 am

Hi all,

I am having some issues trying to make a template for working with homegrown dll's I can now compile dll's and use callDLL as a harness for loading them, and the test.fla example works fine but I am finding it difficult to make my own 'vanilla' version of the fla as an AS3 class; I am using flexbuilder 2 to write an actionscript project.

My first issue is that I get a null reference error when I try to access stage.stageWidth or .stageHeight in the constructor.

The second problem is that when I use a timer to call the dll from a private method, (1000ms interval, repeat 1) the messagebox appears repeatedly untill I get a stack overflow.

The third problem is that when I comment out stage references and call the private method directly rather than on the timers eventhanlder the messagebox pops up once and then flashplayer closes (crashes?)

I am sure there is something fundamentally wrong in my approach that is causing all this unpredictable behaviour XD but I can't seem to work it out.

Any ideas ?

Here is the code - I am very sorry for the lengthy post, but I figured that the more information I could provide the easier it would be for someone to see my oversite :S

 //requires northcode compilation with callDLL.dll 
 
 package {
   
   import flash.display.Sprite;
   import flash.display.BitmapData;
   import flash.display.Bitmap;
   import flash.utils.Timer;
   import flash.utils.getTimer;
   import flash.events.TimerEvent;
   
   public class Main extends Sprite{
      
      private var myTimer:Timer;
      private var screen:BitmapData;
      
      private var WIDTH:uint; 
      private var HEIGHT:uint;
      
      public function Main(){
         
         //snip

         //northcode
         ssCore.init();
         ssDefaults.synchronousCommands = true;
         ssCore.Win.show({});
         ssCore.Plugin.load({plugin:"CallDll", alias:"test"});
         ssDebug.trace("initialised");
         
         //screen = new BitmapData(WIDTH, HEIGHT, false, 0);
         //addChild(new Bitmap(screen) );//debug
         
         //debug
         //snip
         firstFunction();
      }
      //snip
      private function firstFunction():void{
         
         try {
            var r:* = ssCore.test.firstFunction({});
         }
         catch (e:Error){
                                ssDebug.trace("function call to CallDLL failed: ",e.message);
                        }
         
         if (r !== undefined){
            if (r.success)
            {
               ssCore.App.showMsgBox({prompt:"call to 'firstFunction' returned: " + r.result});
            }
            else
            {
               ssCore.App.showMsgBox({prompt:"call to 'firstFunction' failed: " + r.Error.description});
            }
         }
      }
   }
}


Posted by mbd in SWF Studio V3 on May 15 2008, 09:42 am

Talk about hitting all the problems in one fell swoop! :)

QUOTE:
My first issue is that I get a null reference error when I try to access stage.stageWidth or .stageHeight in the constructor.
There will be an FAQ about this:
http://www.northcode.com/forums/showpost.php?p=41684&postcount=4

QUOTE:
The second problem is that when I use a timer to call the dll from a private method, (1000ms interval, repeat 1) the messagebox appears repeatedly untill I get a stack overflow.
We have a known problem report for this but it hasn't been published yet. Make sure you call the showMsgBox asynchronously when calling it within a timer. IMO, you should ALWAYS call dialogs asynchronously since you will need to wait for the user to respond. It should be considered an event-based action, the same way you use the Alert in Flex. If you aren't expecting, or don't care about, data being returned then you should force the call to be async by specifying the sync property as false in the callback object. Otherwise you would use a callback function, which inherently forces the call to be asynchronous.

QUOTE:
The third problem is that when I comment out stage references and call the private method directly rather than on the timers eventhanlder the messagebox pops up once and then flashplayer closes (crashes?)
Make sure you are calling ssCore.Win.show() before trying to open a dialog. You will get an error if the window isn't visible when trying to display a dialog. However, it should not crash the application. I would try making the showMsgBox call asynchronous. I'm thinking there's a timing issue that could be related to the second issue above.


Posted by HMC in SWF Studio V3 on May 15 2008, 09:59 am

wow, thanks for your fast answer,

Actually, I am a little embarrassed about 1, since I already knew that but just wasn't thinking about it in this context.

I call win.show in the constructor - is it neccessary to call it prior to every dialogue ?

I will try going down the async route, thanks for the advice :)

GW


Posted by mbd in SWF Studio V3 on May 15 2008, 10:13 am


QUOTE:
I call win.show in the constructor - is it neccessary to call it prior to every dialogue ?
D'oh! I missed that in your code. You only need to call it once, unless your application gets hidden or minimized.


Posted by HMC in SWF Studio V3 on May 15 2008, 11:09 am

ok, most of your advice has worked out well for me, although I also had to chain the initialisation of the class to be dependent on the completion of show.win, however I am still experiencing problem 3 - message boxes spawning untill stack overflow.

I have switched to calling app.showMsgBox asynchronously and you are right, it doesn't make sense not to treat it as an event, perhaps the problem is that the calls to app.showMsgBox are made within a PM called by the eventhandler for the timer ?

here is my revised code - thanks again for all your help :D

 package {
   
   //snip-----------------------------------------------------------------

      public function Main(){
         
         addEventListener(Event.ADDED_TO_STAGE,initNorthCode);
      }
      private function initNorthCode(e:Event):void{
         
         //northcode
         ssCore.init();
         ssDefaults.synchronousCommands = true;
         ssCore.Plugin.load({plugin:"CallDll", alias:"test"});
         ssCore.Win.show({},{callback:initClass,sync:false});
         removeEventListener(Event.ADDED_TO_STAGE,initNorthCode);
      }
      private function initClass(return_obj:Object, callback_obj:Object, error_obj:Object):void{
         
         WIDTH = this.stage.stageWidth;
         HEIGHT = this.stage.stageHeight;
         
         
         ssDebug.trace("initialised");
         
         screen = new BitmapData(WIDTH, HEIGHT, false, 0);
         addChild(new Bitmap(screen) );//debug
         
         //debug
         myTimer = new Timer(1000,1);
         myTimer.addEventListener(TimerEvent.TIMER, update);
         myTimer.start();
      }
      public function update(e:TimerEvent):void{//debug
         
         var timestamp:uint = getTimer();
         firstFunction();
         ssDebug.trace("fps: " + (1000/(getTimer() - timestamp) ) + "/25" );
      }
      private function firstFunction():void{

         //snip-----------------------------------------------------------------

         if (r !== undefined){
            if (r.success){
               ssCore.App.showMsgBox({prompt:"call to 'firstFunction' returned: " + r.result},{callback:onResponse, sync:false});
            }
            else{
               ssCore.App.showMsgBox({prompt:"call to 'firstFunction' failed: " + r.Error.description},{callback:onResponse, sync:false});
            }
         }
      }
      private function onResponse(return_obj:Object, callback_obj:Object, error_obj:Object):void{
         
         ssDebug.trace("user interacted with msg box: " + return_obj.result);
         return;
      }
      
   //snip-----------------------------------------------------------------

}


Posted by mbd in SWF Studio V3 on May 15 2008, 11:25 am

In another thread someone mentioned that async alone wasn't enough, so perhaps that's what you are seeing here as well. Add a timeout to call showMsgBox so that we can guarantee there won't be a timing issue with Flash's Timer class.

setTimeout(ssCore.App.showMsgBox, 50, {prompt:"call to 'firstFunction' returned: " + r.result}, {callback:onResponse});

Note: You don't need to use the sync property AND a callback function. Using a callback function will ensure the command will execute asynchronously. If you don't need a callback function to handle return data but want the command to be executed asynchronously then set the sync property to false. It doesn't hurt anything to specify both, it's just redundant. Specifying a callback function always wins, regardless of the value of the sync property.


Posted by HMC in SWF Studio V3 on May 15 2008, 11:49 am

I don't want to sound rude but I don't follow :S should I use timeout to delay calls to app.showMsgBox? how does this prevent issues with flash.timer ?

I have read some similar threads now - is it something to do with the order that the commands are going out to swf studio ? BTW I added the Timeout delay to my calls within firstFunction and still get the error :'( Perhaps I should make a recursive function using the showMsgBox callback as a workaround ?


Posted by HMC in SWF Studio V3 on May 15 2008, 12:52 pm

Here's my botchy work around based on a recursive loop, bear in mind that whilst this loop is partially events driven, it doesn't have to be, and you could also add a getTimeout to delay the loop by n milliseconds. Still not an ideal solution - maybe tommorow something better will turn up :D


//snnnnip!---------------------------------------------------

         update({f1:true,f2:true});
      }
      public function update(flags:Object):void{//debug
         
         ssDebug.trace('update called');
         
         if (flags['f1']&& flags['f2']){
            flags['f1'] = flags['f2'] = false;
            
            firstFunction(flags);
            secondFunction(flags);
         }else{ssDebug.trace('waiting'); }
      }
      private function firstFunction(flags:Object):void{
         
         ssDebug.trace('first function called');
         
         try {
            var r:* = ssCore.test.firstFunction({});
         }
         catch (e:Error){
                ssDebug.trace("function call to CallDLL failed: ", e.message);
            }
         
         if (r !== undefined){
            if (r.success){
               ssCore.App.showMsgBox({prompt:"call to 'firstFunction' returned: " + r.result},{callback:onResponse,f:flags, sync:false});
               }
            else{
               ssCore.App.showMsgBox({prompt:"call to 'firstFunction' failed: " + r.Error.description},{callback:onResponse, f:flags, sync:false});
            }
         }
      }
      private function onResponse(return_obj:Object, callback_obj:Object, error_obj:Object):void{
         
         ssDebug.trace("user interacted with msg box: " + return_obj.result);
         callback_obj.f['f1']=true;//clear flag
         update(callback_obj.f);//call recursively and clear the first flag
      }
      private function secondFunction(flags:Object):void{
         
         ssDebug.trace('second function called');
         
         //would have a callback for an eventhandler which calls recursively and clears the second flag
         flags['f2']=true;//clear flag
         update(flags);
      }