Search

Writing COM Components in Perl Part 2

1 views

Setting up the ActivePerl Development Kit (PDK) environment

To turn a Perl script into a COM component you first need a toolset that can wrap the code, generate the necessary IDL definitions, and package everything into a DLL. ActiveState’s Perl Development Kit (PDK) does that job. Download the installer from ActiveState’s website and install it. Once the interpreter is in place, run the PDK installer. The wizard presents a few screens that let you choose where to put the kit and which optional components to install. The defaults work fine for most users, so simply hit Next through the prompts and let the installer finish. After the process ends, the kit sits in a folder named ActivePerl by default, though you can pick a different location during installation.

Navigate to the bin subdirectory inside the installation folder. Here you’ll find a script named PerlCtrl.pl. That script is the command‑line driver that the PDK uses to generate COM wrappers, IDL files, and DLLs. For convenience, add the full path to PerlCtrl.pl to your system’s PATH environment variable. On Windows, you can do that by opening System Properties → Advanced → Environment Variables, editing the PATH entry, and appending the path to the bin directory. Once the path is set, open a new command prompt and type PerlCtrl.pl. If the PATH was configured correctly, you should see a help screen with usage information. If you receive an error that the command is not recognized, double‑check the PATH entry or invoke the script with its absolute path, for example c:\ActivePerl\bin\PerlCtrl.pl With the tool ready, you’re now able to experiment with COM generation. The next step is to write a Perl class that you wish to expose. While you can start with a simple example, the tutorial will walk you through creating a WebMail component that sends email through an SMTP server. The code will live in a file called WebMail.pm and will use the CPAN module Mail::Sender. Make sure that module is installed before you proceed. Install it with CPAN or from the ActivePerl package manager by executing cpan Mail::Sender or selecting it in the package manager’s interface. The component will call Mail::Sender to handle the heavy lifting, while the COM layer handles type conversion and registration.

Now you are positioned to write the Perl code, generate the COM metadata, build the DLL, register it, and test it from an ASP page. The following sections detail each of these stages. You’ll learn how to customize the automatically produced template, how to tweak the build options for freestanding or dependent components, and how to troubleshoot common pitfalls such as licensing prompts or missing modules.

Crafting your Perl class for COM

When you write a Perl class that you intend to expose through COM, think of it as a normal module that can also respond to method calls from external clients. The example below shows a module named WebMail that contains two public methods: send and getError. The send method accepts a string for every field that you might need when sending an email - sender, reply‑to, recipient lists, subject, body, and an optional attachment list. The return value is a boolean indicating success or failure, encoded as for true and for false. This mapping is deliberate because VBScript and ASP use True and False for boolean values, and is the numeric representation that COM expects for VT_BOOL The module starts with package WebMail; and uses Mail::Sender for the actual SMTP communication. Inside send, it creates a new Mail::Sender object, passing all arguments via a hash. If construction fails, send returns . Otherwise it calls either MailMsg or MailFile depending on whether an attachment string is provided. The method captures any failure by checking the return value of these calls. When the message is sent successfully, the Mail::Sender object is closed and the boolean success flag is returned. getError simply returns the global $Mail::Sender::Error string, allowing the caller to retrieve a diagnostic message on failure.

The logic inside send is intentionally straightforward. Because the component will be used from an ASP script, we avoid throwing Perl exceptions; instead we capture errors and surface them through getError. The Mail::Sender module handles all the RFC‑compliant details of SMTP conversation, including authentication if the server requires it. The module can also send MIME attachments because the MailFile method accepts a list of filenames, each represented as a string or array reference. For the purposes of this tutorial, the attachment list is expected to be a comma‑separated string of absolute paths, but you can adapt the logic to any format you prefer.

Because the component is wrapped by the PDK, the only additional requirement is to provide a metadata template that describes the methods and properties to COM. The template is a Perl hash that lists the package name, GUIDs, ProgID, and method signatures. We’ll cover how to generate that template and tweak it to match our WebMail class in the next section. Once you have both the Perl module and the template, the PDK can generate a DLL that registers the component under a ProgID like WebMail.Mailer. From there, any COM‑capable client - VBScript, ASP, or a C++ application - can instantiate WebMail.Mailer and call send as if it were a native COM object.

Generating and refining the COM template

The PDK creates a metadata file that tells COM what methods and properties exist on your object, what types they accept, and what types they return. This file is not handwritten from scratch; you let the tool generate a skeleton and then adjust it. At a command prompt, run PerlCtrl.pl -t while your current directory contains WebMail.pm. The tool scans the module, looks for public subroutines, and writes a template that looks like a Perl hash. The output is wrapped between =POD and =END PerlCtrl markers. The skeleton contains placeholders for package name, GUIDs, and a list of methods with their parameters and return types. Because the PDK uses Variant data types, each parameter is described as a VT_* constant such as VT_BSTR for strings or VT_BOOL for booleans. The TypeLibGUID, ControlGUID, and DispInterfaceIID fields are auto‑generated UUIDs that must not be changed; they uniquely identify the component in the registry.

Open the generated file in your favorite editor. The first few lines define the package name; change 'MyPackage::MyName' to 'WebMail'. The ControlName should match the ProgID you plan to use, for example 'WebMail.Mailer'. The ProgID field is what clients will pass to CreateObject. Set DefaultMethod to an empty string unless you want a default method; COM clients rarely call an object without naming a method. The Methods hash is where the meat of the template lives. For each public method, add an entry: the key is the method name, and the value is a hash containing RetType, TotalParams, NumOptionalParams, and ParamList. In our case, send takes nine string parameters and returns a boolean, so RetType is VT_BOOL, TotalParams is 9, and ParamList lists the nine names each mapped to VT_BSTR. The getError method takes no parameters and returns a string, so its RetType is VT_BSTR and TotalParams is 0.

If your class had properties - read‑only or read‑write values - you would list them under the Properties hash. Each property entry would specify Type and ReadOnly flags. In the WebMail example we don’t expose any stateful properties, so the Properties section can remain empty. Once you’ve finished editing the template, save the file and append it to the end of WebMail.pm after the final 1; line. That placement tells the PDK that the template belongs to this module.

With the template in place, the PDK can now create a COM wrapper. Two build options are available: -f for a freestanding DLL that bundles a Perl interpreter, and -d for a dependent DLL that relies on an external Perl installation. Freestanding DLLs are larger but portable; dependent DLLs are smaller and require Perl on the target machine. Choose -f if you plan to distribute the component to clients who may not have Perl installed. To build the freestanding DLL, run PerlCtrl.pl -f WebMail.pm. The tool will scan your module, resolve all require statements, and package the module along with the interpreter and any CPAN modules it uses.

During the build, the PDK may print lines such as Adding Module: C:/APPS/ActivePerl/site/lib/MIME/Base64.pm to indicate which files are being bundled. If you use the dependent build, many of these lines will be omitted because the target system is expected to provide those modules. Keep an eye out for license prompts; the free trial of the PDK expires after a certain number of builds. If you see a message like Your license has expired. Please purchase a license, visit https://www.ActiveState.com/cgibin/license/pdk12/newtrial.pl to obtain a new key. Run the downloaded installer to register the license, then repeat the build command.

After the build completes, you will have a file named WebMail.dll in the same directory. This DLL contains the COM implementation of your WebMail class and can be registered with the system. Registration is the next logical step.

Building, registering, and testing the COM component

Register the freshly created DLL by opening a command prompt with administrative rights and executing regsvr32 WebMail.dll. If the registration succeeds, a dialog will appear confirming that the component was registered. On Windows 10 and later, the dialog might be suppressed, but you can verify the registration by opening the Registry Editor and navigating to HKEY_CLASSES_ROOT\WebMail.Mailer. Under this key, you should see entries for CLSID, InProcServer32, and ProgID that point back to WebMail.dll. If you encounter an error during registration, make sure the DLL path is correct and that you are using an elevated command prompt.

Once the component is registered, you can test it from an ASP page. Create a file named SendMail.asp in your web root and paste the following code. The script creates an instance of WebMail.Mailer, calls the send method with placeholder values, and checks the return value. If the call fails, the script prints the error string; otherwise it reports success. Replace the placeholder text - [FROM], [TO ADDRESS], etc. - with real values. For attachments, pass a comma‑separated list of absolute file paths; Mail::Sender will read and attach them. If you need to use an SMTP server that requires authentication, extend the send method to accept username and password parameters and pass them to Mail::Sender <% option Explicit Dim mailer, sent Set mailer = Server.CreateObject("WebMail.Mailer") sent = mailer.send("[FROM]","[REPLY TO ADDRESS]","[TO ADDRESS]","[CC ADDRESS/ES]","[BCC ADDRESS/ES]","[SMTP SERVER IP ADDRESS]","[SUBJECT]","[MESSAGE BODY]","[FILE/S TO ATTACH]") If sent = False Then Response.Write(mailr.getError()) Else Response.Write("Message sent") End If %>

After you save the file, run it in a browser. If everything is wired correctly, you should see the “Message sent” message. If the email fails to deliver, the page will display the diagnostic string returned by getError. Check the SMTP server logs if you still can’t find the issue; sometimes network or firewall settings prevent outbound connections on port 25 or 587. Remember that the component relies on the Mail::Sender module, so any configuration required by that module - such as enabling TLS or setting a custom port - needs to be reflected in the arguments you pass to send From a maintenance standpoint, the PDK workflow is straightforward. To update the component, edit the WebMail.pm file and its embedded template. Do not modify the auto‑generated GUIDs; keeping them stable preserves the ProgID and allows clients to keep referencing the same component. After making changes, run regsvr /u WebMail.dll to unregister the old DLL, rebuild with PerlCtrl.pl -f WebMail.pm, and re‑register with regsvr32 WebMail.dll. Repeat the test page to verify the new behavior. By following this cycle, you can iterate on the component’s functionality while ensuring that the COM interface remains stable for consuming applications.

Suggest a Correction

Found an error or have a suggestion? Let us know and we'll review it.

Share this article

Comments (0)

Please sign in to leave a comment.

No comments yet. Be the first to comment!

Related Articles