Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Database

Examining PerlCOM


Jan00: Programmer's Toolchest

Mike is an instructor of computer science at Pulaski Technical College, contract programmer, and author of Perl From the Ground Up (Osborne, 1999). You can contact Mike at [email protected].


When O'Reilly & Associates released its Perl Resource Kit for Win32, it did more than just put the Perl language into a shrinkwrap package -- it also provided programmers with a new set of tools that extend the already powerful Perl language. One of the most interesting tools is PerlCOM, which lets you use Perl in any language or application that supports Microsoft Component Object Model (COM) objects. In this article, I'll describe the PerlCOM component and show you how to use it to extend Visual Basic to include features such as a regular expression engine and the ability to access Perl modules from within Visual Basic. The Perl community has created a useful set of modules that extend Perl to do things such as network programming, text manipulation, and editing the Registry. Using PerlCOM, you can create an instance of a Perl module and use Visual Basic to access the module's methods and properties. Programming with PerlCOM provides you an alternative to the Windows API or other libraries. PerlCOM can also be used with DCOM to provide distributed access to Perl.

Introducing PerlCOM

PerlCOM is a component that puts a wrapper around a single Perl interpreter. Using the PerlCOM object (PerlCOM.Script), you can execute Perl code from within an application or a development environment such as Visual Basic. You can create and execute Perl functions, as well as create Perl variables and access them using the host language. You can also work with Perl modules. If you are working in a distributed environment, PerlCOM works with DCOM as well as COM, meaning that if you have Perl and the PerlCOM DLL loaded on a server, any client on the network can access and run Perl code from the server.

The first step in using PerlCOM is to create an ActiveX object using the Visual Basic CreateObject function:

Dim objPerl As Object

Set objPerl = CreateObject("PerlCOM.Script")

The named object, objPerl, is now bound to a single instance of the Perl interpreter through the common name for the PerlCOM DLL, PerlCOM.Script. With the object defined and bound, you can now execute Perl code using the EvalScript method. This first example simply declares a scalar variable and assigns a value to it:

objPerl.EvalScript "$greet = 'Hello, world.\n' ;"

To access this newly created variable, you have to treat it as a property of the PerlCOM object it is defined under, like this:

MsgBox objPerl.greet

objPerl.greet = "Hello, gentle reader."

The first line displays the greeting "Hello, world." in a message box, and the second changes the greeting to another string. The second line of code is interesting because you are taking a variable created with Perl code and changing its value using Visual Basic code. The initial value of the variable doesn't have to be set under Perl, though the variable does have to be initialized, like this:

objPerl.EvalScript "$greet="

objPerl.greet = "Hello, world."

You can also create a Perl function using the EvalScript method, then run it from within Visual Basic as a method of the PerlCOM object. Listing One displays a greeting in a message box. The name of the Perl function created with EvalScript is my_greet. The shift operator is used to pull the function argument in as the value of the scalar variable $name. The term qq is a quote operator that puts double quotes around its argument, which in Listing One is bracketed so that the whole expression is double quoted. Finally, because Perl does variable interpolation, the $name variable is combined with the word "Hello" to display a personalized greeting.

PerlCOM Arrays

Perl is often used to process lists of data using array data structures. Returning an array from Perl to be evaluated in Visual Basic is straightforward. After you have built an array in Perl, simply return a reference to the array (such as \@array instead of just @array) and Visual Basic will convert it to a Basic array.

Listing Two creates a Perl function that splits a string into an array. The array is then passed as a reference to Visual Basic, where the array is built back into a string and displayed element by element in a message box.

Using PerlCOM::Hash

A hash is an associative array that organizes data into key/value pairs. This data structure is called a "hash" due to the underlying algorithm (the hash table) that is used to implement it. Listing Three, which demonstrates how a simple hash is created in Perl, displays the name "L. Wall."

This associative structure can be built using PerlCOM in two ways. One way is to write a function in Perl that returns a reference to a hash, and evaluate the code using the EvalScript function; see Listing Four. The code evaluated by the EvalScript function creates the hash using the same code as I used in the aforementioned Perl example. After the hash is created, a Visual Basic hash object is created and is assigned the hash by calling the build_ hash property. Finally, a value is returned and displayed in a message box by calling the Get property. This property takes a hash key and returns its associated value.

It is also possible to create a hash without actually writing any Perl code. The CreateHash function returns a hash object and then allows you to define each key as a property of the object and the key's associated value can be assigned to the property. Listing Five creates the Wizards hash using this technique.

Another way to assign a key and value to a hash is to use the Set method, which takes the key and the value as quoted arguments, like this:

objWizards.Set "Fortran", "J. Backus"

The first element is the key and the second one is the value that is returned by the key.

While you will often want to work with a hash by retrieving a value from a key reference, there are also times when you will want to work with the whole key/value pair. PerlCOM provides a useful method for returning this data pair -- the Each() method. This method returns the key/value pair as array items, with the key being the 0th element and the value being the 1st element. The most common use of the Each() method is to iterate through a hash, performing some operation or set of operations on each key/value pair. Listing Six loops through the Wizards hash, displaying each key/value pair in a listbox. This produces output such as:

Java => J. Gosling

Perl => L. Wall

Fortran => J. Backus

When the Each() method is called, the key/value pair is stored in the array elements arrayPair(0) and arrayPair(1). When the hash is out of data, the method will return a null list, and the variable will be empty. While the variable arrayPair is not initialized as an array, the Each() method still stores the contents of each key and value as an array element. This behavior matches the Perl function each, which returns the key/value pair of a hash as a list.

PerlCOM and Perl Modules

Perl modules extend the functionality of Perl by providing libraries for performing operations that aren't possible using just plain Perl. There are modules for working with files, working with the Internet, working with the Registry, and just about every standard and esoteric computational function you can imagine. PerlCOM gives you access to these modules through the UsePackage method and the CreateObject method that I've already looked at. If the Perl module you want to use is a collection of functions, you will use the UsePackage method. However, if the module you want to use consists of class definitions that can be instantiated into objects, then you will use the CreateObject method.

When the module you want to import is made up of standard Perl functions, you use the UsePackage method to import the functions into Visual Basic. To illustrate how to use this method with PerlCOM, I'll examine the Win32.pm module, which imports a group of functions that provide information about the current Win32 operating environment and perform various operations on Win32 machines, such as system shutdowns and registering and unregistering ActiveX/COM servers.

Once a PerlCOM object is created, you simply call the UsePackage method with the name of the module you want to import; see Listing Seven. All of the module's functions are now imported into Visual Basic and can be called as properties of the PerlCOM object. Listing Eight gets the local user name and computer name from a Win32 machine and displays them.

When you use a module that is made up of class definitions, you use the CreateObject method to import the module into your Visual Basic program. For example, the FileHandle module provides a set of methods and properties that make it easy to work with files in Perl. This module is object oriented and must be imported with PerlCOM via the CreateObject method. Listing Nine creates a new instance of a FileHandle object.

The FileHandle module's properties can now be called as properties of the objFileHdl, the new FileHandle object. Listing Ten uses the FileHandle method to get lines from a text file and make a text substitution in each line when a particular string is found. This code demonstrates how to do pattern substitutions with Perl in Visual Basic. The purpose of Listing Ten is to find each instance of the substring dp in the given text file and change the substring to cis. This is done quite easily in Perl by doing a pattern substitution of cis for each occurrence of dp (the regular expression s/dp/cis) and reassigning it to the line of text using Perl's binding operator (=~). However, to do this, you first create a Perl variable so that you can store data in it. This is done by creating an empty variable using the EvalScript method. The data is grabbed from the text file using the getline method from the FileHandle module. Finally, each line of the text file is displayed in a listbox with the new text substituted if a pattern match is found.

Conclusion

The goal of PerlCOM is to expose a Perl interpreter that can be invoked from within another COM-aware programming language or application. The examples I've shown here were written within the Visual Basic environment, but I could have also shown you how to use PerlCOM from within Microsoft Word or Excel, Delphi, or even PowerBuilder. Most importantly, PerlCOM lets you use the power and flexibility of Perl in other environments that may not be quite as powerful or flexible. As the Visual Basic family of languages -- Visual Basic, Visual Basic for Applications, Visual Basic Scripting Edition -- mature and develop, they will undoubtedly gain some of the power and flexibility of Perl.

In fact, just in the past few months I have been exploring PerlCOM, the 5.0 Version of Visual Basic Scripting Edition includes a regular-expression engine and more hooks into the operating system. Still, it will be hard for Microsoft to match in number or usefulness the modules that have been and are being created for the Win32 version of Perl. For the foreseeable future, it will be advantageous for you to explore and use PerlCOM as an efficient way to extend the Visual Basic environment.

DDJ

Listing One

objPerl.EvalScript " sub my_greet { "   & _
                   "    my $name = shift; "     & _
                   "    return qq[Hello, $name.]; } "
strName = "Charlie"
MsgBox objPerl.my_greet(strName)

Back to Article

Listing Two

Dim objPerl As Object
Set objPerl = CreateObject("PerlCOM.Script")
objPerl.EvalScript (" sub str_split { " & _
                    "  $string = 'Perl,C,Java,C++';" & _
                    "  my @languages = split(/,/, $string);" & _
                    "  return \@languages; } ")
arrayLangs = objPerl.str_split()
strLangs = ""
For x = 0 To UBound(arrayLangs)
   strLangs = strLangs & arrayLangs(x) & Chr(13) & Chr(10)
Next x
MsgBox strLangs

Back to Article

Listing Three

My %wizards = (
   C     => 'D. Ritchie',
   Java => 'J. Gosling',
   Perl => 'L. Wall',
);
print $wizards{"Perl"} 

Back to Article

Listing Four

Dim objPerl As Object
Set objPerl = CreateObject("PerlCOM.Script")
objPerl.EvalScript _
    " sub build_hash { " & _
    "    my %wizards = ( 'C'    => 'D. Ritchie', " & _
    "                    'Java' => 'J. Gosling', " & _
    "                    'Perl' => 'L. Wall'); " & _
    "    return \%wizards } "
Dim oHash As Object
Set oHash = objPerl.build_hash
MsgBox oHash.Get("Perl")

Back to Article

Listing Five

Dim objPerl As Object
Set objPerl = CreateObject("PerlCOM.Script")
Set objWizards = objPerl.CreateHash
objWizards.C = "D. Ritchie"
objWizards.Java = "J. Gosling"
objWizards.Perl = "L. Wall"
MsgBox objWizards.Get("Java")

Back to Article

Listing Six

Dim objHash As Object
Dim arrayPair 
Set objHash = objPerl.CreateHash
objHash.C = "D. Ritchie"
objHash.Java = "J. Gosling"
objHash.Perl = "L. Wall"
objHash.Set "Fortran", "J. Backus"
arrayPair = objHash.Each()
Do While (Not IsEmpty(arrayPair))
   List1.AddItem arrayPair(0) & " => " & arrayPair(1)
   arrayPair = objHash.Each()
Loop

Back to Article

Listing Seven

Dim objPerl As Object
Set objPerl = CreateObject("PerlCOM.Script")
Set objWin32 = objPerl.UsePackage("Win32")

Back to Article

Listing Eight

strUserName = objWin32.LoginName
strComputerName = objWin32.NodeName
strInfo = "User name: " & strUserName & Chr(13) & Chr(10)
strInfo = strInfo & "Computer name: " & strComputerName
MsgBox strInfo, , "User Information"

Back to Article

Listing Nine

Dim objPerl As Object
Set objPerl = CreateObject("PerlCOM.Script")
Set objFileHdl = objPerl.CreateObject("FileHandle", "new")

Back to Article

Listing Ten

strFileName = "c:\sample.txt"
If objFileHdl.open(strFileName) = 1 Then
   For x = 1 To 4
      objPerl.EvalScript "$dept = '';"
      objPerl.dept = objFileHdl.getline
      objPerl.EvalScript "$dept =~ s/dp/cis/;"
      List1.AddItem objPerl.dept
   Next x
   objFileHdl.Close
End If

Back to Article


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.