You are here: Recent News » Using a SWF as a DLL

 

Using a SWF as a DLL

A tutorial by Aral Balkan

Charles Iliya Krempeaux asked a question on the MTASC list on how to create and use dynamically linked libraries in Flash.

When you write software in another language, you can create "libraries".  
For example, if I were writing code in C#, then I could create .dll files 
(which would contain classes, etc that I could use in other programs). 
Is there a way to do this with ActionScript?

You can create DLLs in Flash – in fact, a DLL is nothing more than a regular SWF that only contains classes.

The process is simple:

Download the source and example: dll_loader.zip (25kb)

Creating the library (DLL) SWF

  1. Create a folder for your project (SWF DLL Test)
  2. Inside the folder create a folder for your library (library) and one for your application (application). The application will load in and use the DLL.
  3. Create an FLA for your library in the library folder called dll.fla)
  4. In its first frame, import the classes you want to include in this library.
    import com.ariaware.tests.dll.library.*;
  5. In this example, you have two classes in your library, FirstClass and SecondClass, which you’ve placed in the com.ariaware.tests.dll.library package. Merely importing them is not enough to have them compiled into your DLL SWF, you must actually reference them so add the following code to the first frame of your FLA:
    // Reference the classes so that they get compiled into the DLL
    FirstClass;
    SecondClass;
  6. The two classes are simple (and almost identical). Here is the FirstClass for your library:
    class com.ariaware.tests.dll.library.FirstClass
    {
    	function FirstClass()
    	{
    		trace ("FirstClass constructor");
    	}
    	
    	function aMethod()
    	{
    		trace ("FirstClass.aMethod()");
    	}
    }
  7. And the SecondClass:
    class com.ariaware.tests.dll.library.SecondClass
    {
    	function SecondClass()
    	{
    		trace ("SecondClass constructor");
    	}
    	
    	function aMethod()
    	{
    		trace ("SecondClass.aMethod()");
    	}
    }
  8. Compile your library. This should create a SWF called dll.swf in your /library folder.

Setting up your application and using the DLL Loader

  1. In your application folder, create a new FLA called application.fla
  2. In your application FLA, create a new Movie Clip symbol called Application and link it to the class com.ariaware.tests.dll.Application. Here is the code for the Application class:
    import com.ariaware.tests.dll.library.*;
     
    import com.ariaware.arp.utils.dll.DLLLoader;
    import com.ariaware.arp.utils.dll.DLLEvent;
     
    import mx.utils.Delegate;
     
    class com.ariaware.tests.dll.Application extends MovieClip
    {
    	// On stage
    	var dllLoader:DLLLoader;
    	var txtPreloader:TextField;
     
    	// Event listener delegates
    	var progressDelegate:Function;
    	var completeDelegate:Function; 
    	
    	private function onLoad()
    	{
    		// Create delegates so we have method closures
    		progressDelegate = Delegate.create ( this, dllProgress );
    		completeDelegate = Delegate.create ( this, dllComplete );
    		
    		// Listen for preloader events on loader
    		dllLoader.addEventListener ( "progress", progressDelegate );
    		dllLoader.addEventListener ( "complete", completeDelegate );
    													
    		// Load the DLL
    		dllLoader.loadDll ( "../library/dll.swf" );
    	}
    	
    	//
    	// Event handlers
    	//
    	
    	// Called on DLL load progress
    	private function dllProgress ( evt:DLLEvent )
    	{
    		var bytesLoaded:Number = evt.bytesLoaded;
    		if ( bytesLoaded <= 100 )
    		{
    			txtPreloader.text = "Waiting to load...";
    		}
    		else
    		{
    			txtPreloader.text = Math.round ( evt.bytesLoaded * 100 / evt.bytesTotal ) + "% loaded.";
    		}
    	}
    	
    	// Called when the DLL has completely loaded
    	private function dllComplete ( evt:DLLEvent )
    	{
    		// Remove preloader event listeners
    		dllLoader.removeEventListener ( progressDelegate );
    		dllLoader.removeEventListener ( completeDelegate );
    		
    		// Display status message
    		txtPreloader.text = "DLL Loaded!";
    		
    		//
    		// Test the library classes
    		//
    		var firstClass:FirstClass = new FirstClass();
    		firstClass.aMethod();
    		
    		var secondClass:SecondClass = new SecondClass();
    		secondClass.aMethod();
    	}
    }
  3. Notice that when the DLL finishes loading in, the dllComplete event handler gets called. Here you refer to FirstClass and SecondClass but, when you compile Application.fla you don’t want to add these classes to your SWF (this would really defeat the purpose of using a DLL!) But if you don’t load in the classes, the Flash compiler will give you an error. What to do? Intrinsic classes to the rescue. If you create intrinsic classes for each class that you will use from your library, you won’t get any compile-time errors and you’ll benefit from compile time type-checking on linked classes. Here is the code for the intrinsic FirstClass class:
    intrinsic class com.ariaware.tests.dll.library.FirstClass
    {
    	public function aMethod():Void;
    }
  4. The intrinsic SecondClass class is almost identical. Notice how the fully-qualified class name for the intrinsic classes is identical to the fully-qualified class name of the actual classes in the Library.
    intrinsic class com.ariaware.tests.dll.library.SecondClass
    {
    	public function aMethod():Void;
    }
  5. Create a new Movie Clip Symbol called DLLLoader and link it to the class com.ariaware.arp.utils.dll.DLLLoader. Here is the code for the DLLLoader class:
    import mx.events.EventDispatcher;
    import com.ariaware.arp.utils.dll.DLLEvent;
     
    class com.ariaware.arp.utils.dll.DLLLoader extends MovieClip
    {
    	// On Stage
    	var deadPreview:TextField; 
    	
    	// Dynamically created clips
    	var loaderShell:MovieClip = null;
    	
    	//
    	// Group: Events broadcast
    	//
    	// Event: progress - On load progress (every frame)
    	// Event: complete - When DLL has completely loaded
    	// 
    	
    	public function DLLLoader ()
    	{
    		EventDispatcher.initialize ( this );
    	}
    	
    	////////////////////////////////////////////////////////////////////////////
    	//
    	// Method: loadDll()
    	//
    	// Starts loading the specified DLL (SWF) file. A valid DLL file is a 
    	// SWF file that contains AS2 classes.
    	//
    	////////////////////////////////////////////////////////////////////////////	
    	public function loadDll ( dll:String )
    	{
    		// Create shell movie clip to load DLL into if it doesn't already exist
    		if ( loaderShell == null )
    		{
    			loaderShell = createEmptyMovieClip ( "loaderShell", getNextHighestDepth());
    		}
    		
    		// Load the movie
    		loaderShell.loadMovie ( dll );
    		
    		// Start the preloader
    		onEnterFrame = preloader;
    	}
    	
    	////////////////////////////////////////////////////////////////////////////
    	//
    	// Group: Private methods
    	//
    	////////////////////////////////////////////////////////////////////////////
     
    	private function onLoad ()
    	{
    		deadPreview._visible = false;
    	}
    	
    	// Preloader method called every frame after DLL starts loading
    	private function preloader ()
    	{
    		var bytesLoaded:Number = getBytesLoaded();
    		var bytesTotal:Number = getBytesTotal();
    		if ( bytesLoaded == bytesTotal && bytesLoaded > 10 )
    		{
    			// Ok, DLL has loaded -- wait a frame for it
    			// to initialize so the classes become available.
    			onEnterFrame = waitForInit;
    		}
    		else
    		{
    			dispatchEvent ( new DLLEvent ( "progress", bytesLoaded, bytesTotal ) );
    		}
    	}
    	
    	// DLL has initialized. Broadcast the complete event
    	private function waitForInit ()
    	{
     
    		onEnterFrame = null;
    		dispatchEvent ( new DLLEvent ( "complete", getBytesLoaded(), getBytesTotal() ) );		
    	}
    	
    	//
    	// Note: Methods to be mixed in by the EventDispatcher
    	//
    	function addEventListener(){};
    	function removeEventListener(){};
    	function dispatchEvent(){};
    }
  6. The DLLEvent class is very simple:
    class com.ariaware.arp.utils.dll.DLLEvent 
    {
    	var type:String;
    	var target:Object;
     
    	var bytesLoaded:Number;
    	var bytesTotal:Number;
    	
    	function DLLEvent ( type, bytesLoaded, bytesTotal )
    	{
    		this.type = type;
    		this.bytesLoaded = bytesLoaded;
    		this.bytesTotal = bytesTotal;
    	}
    }
  7. In the Application symbol, place a new text field (which you’ll use as a simple preloader), and give it the instance name txtPreloader.
  8. Drag an instance of the DLLLoader movie clip symbol into your Application symbol (form).
  9. Finally, drag an instance of the Application movie clip symbol (form) on to the Stage so that it will get initialized when the movie is tested.
  10. Test the Application movie to see the DLL get loaded in and the linked classes used.

Note: Unless otherwise stated, all code is released under the MIT license (I’ve removed some comments, license notes, etc. from the code to make it easier to read online.) Full license information can be found in the source download.

I will be adding the DLLLoader and DLLEvent classes to the experimental branch of ARP.

Download the source and example: dll_loader.zip (25kb)

A Simpler Method: Using exclude.xml

In response to the tutorial, Clément Arnoux wrote the following on OSFlash mailing list:

 First of all, why for such a simple example didn't you talk about the exclusion xml 
 as a possible solution along with intrinsic classes?

Clément’s right: Using an exclude.xml file here (instead of intrinsic classes) is a viable alternative. It means that you can include the actual library in your classpath but, using the exclude.xml file, tell Flash to not include the library classes in your final SWF. It will offer you all the same advantages as using an intrinsic file (such as compile-time type checking), along with a couple of extras (the most important being that you won’t have to update the interfaces of your intrinsic classes whenever your actual class interfaces change.)

The only difference between the intrinsic class and exclude.xml methods is the following:

Instead of creating intrinsic classes for each class in your library, you create a single exclude.xml file and name it nameOfYourFLA_exclude.xml. Here is the listing of the exclude XML file for this example:

<excludeAssets>
	<asset name="com.ariaware.tests.dll.library.FirstClass" />
	<asset name="com.ariaware.tests.dll.library.SecondClass" />
</excludeAssets>

Download the source and example: dll_loader_exclude_xml.zip (23kb)

using_a_swf_as_a_dll.txt · Last modified: 2005/06/28 12:32 by aral