Click here to Skip to main content
15,885,546 members
Articles / Desktop Programming / MFC

CPerlWrap - A class wrapper for embedding Perl into your MFC program

Rate me:
Please Sign up or sign in to vote.
4.85/5 (23 votes)
23 Feb 2012CPOL10 min read 215.8K   2.2K   90  
Simple class to allow fast, easy access to Perl and Perl variables.
// PerlWrapSTL.h : header file
//
// Simple wrapper based on Perl guts and embed pages.
//
// 7/30/2003 -- converted to use Perl58, and Perl headers moved
//                    to PerlWrap.cpp to avoid polluting namespace
//                    (see PXPerl at www.codeproject.com for another Perl wrapper)
//   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//   From CPerlWrap project on CodeProject.com


// 12/15/2003 jwilde
//                              Converted to STL from MFC


#if !defined(PERLWRAPSTL_H)
#define PERLWRAPSTL_H

#if _MSC_VER > 1000
#pragma once
#endif

// Adjust this to point to the proper .lib file for Perl on your machine
// Remember to package Perl58.dll along with your project when you install
// onto other machines!
#if !defined(NOIMPLINK) && (defined(_MSC_VER) || defined(__BORLANDC__))
//#     pragma comment(lib,"C:/Perl/lib/CORE/Perl58.lib")
#	pragma comment(lib,"C:/Perl/lib/CORE/perl514.lib")
#endif


#include <string>
#include <vector>
#include <map>

////////////////////////////////////////////////////////////////////////////////
// To get the Perl CORE files you need to add an include path:
//
// In Project->Settings...
//      Settings for: All Configurations
//      C/C++ tab
//           Category: Preprocessor
//                Additional include directories:
//                C:\Perl\lib\CORE
//
// If the pragma 'comment' above doesn't work (or offends you) then do
// the following instead:
//
// Add library path:     c:/Perl/lib/CORE
// Add library file:     Perl514.lib   (or Perl.lib if you have it renamed)
//
// See the perlembed web page for details. But be aware that the page is
// not completely up to date. For instance, the genmake stuff just doesn't
// seem to work (at least not under cygwin).
//
/////////////////////////////////////////////////////////////////////////////////




/////////////////////////////////////////////////////////////////////////////////
// This class is a very basic wrapper for the Perl .dll (Perl58.dll) running
// as a thread within the current process. Support for multiple instances of
// Perl (in different threads) is provided. Each instantiation of a CPerlWrapSTL
// gets its own instance of Perl running in its own thread.
//
// One major limitation is that if you are using modules (other than Perl
// pragmas like 'use warning;' or 'use int;') then the machine must have a full
// Perl installation. If the modules are pure Perl code (such as CGI) then you
// can work around this by including a copy of the subdirectory needed by the
// module. Perl expects a particular structure and modifying that is beyond me.
//
// However, if you are just using straight Perl (regex, lists, hashes, etc.) then
// all you need at runtime is Perl58.dll. You still need the Perl installation
// to compile the program, particularly the CORE headers.
//////////////////////////////////////////////////////////////////////////////////

typedef std::vector<std::string>   string_vector;

// does this need to be a multimap?
typedef std::map<std::string,std::string> string_map;



class CPerlWrapSTL
{
	// Construction
public:
	CPerlWrapSTL();
	
	// Attributes
private:
	// Use void* to keep down the namespace pollution
	//PerlInterpreter *my_perl;     // current instance of Perl
	//SV *last_eval;               // return VALUE from last eval() (not success/fail)
	void *last_eval;               // return VALUE from last eval() (not success/fail)
	void *my_perl;                    // current instance of Perl
	
	std::string eval_error;               // error message from last eval (found in $@)
	bool failOnWarning;               // set if any warnings constitute a failure of doScript()
	bool clearWarningsOnScript;     // set if warnings are cleared before executing a script
	
	// Operations
	
	// I discovered by accident that the comment on the same line as the method declaration
	// is displayed by Visual Studio in the class members drop-down list. That is, to use
	// Intellisense in Visual Studio, this is how it is done.
	//
	// For instance, if I have an instance of CPerlWrapSTL called perlInst and I type in
	// 'perlInst.' then a drop-down list of all available members is displayed. As you
	// continue to type (perlInst.getA) the selection has terse recognition and will scroll
	// down to getArrayVal and the comment 'get array (@varName) as a CStringArray' will be
	// displayed as a hint. Well, that hint is the comment on the declaration line. So if
	// the comments below seem pendantic, it is to support that drop-down box!
	
public:
	// NOTE: There are gotchas here: Since the script runs in its own eval{},
	// variables declared with 'my' are transitory and local to the script. That is,
	// if you declare 'my @myarray = (1,2,3);' and then run the script and followed by a
	// call to getArrayVal("myarray", myarray), it will fail -- there is no longer any
	// such list since the script has gone out of scope. But if you said something
	// like '@myarray = (1,2,3);' and then used getArrayVal(), you will get a CStringArray
	// with all 3 elements. Naturally, if you have 'use strict;' turned on, you will
	// have to predeclare all 'globals' with the set*Val() functions or you will get
	// errors.
	
	// If there was a fatal error or exception in the script, this returns FALSE.
	bool     doScript(std::string script);     // execute the script, use other funcs to get results
	
	// These are used to create and populate arbitrary variables.
	// Good for setting up data to be processed by the script.
	// They all return TRUE if the 'set' was successful.
	bool     setIntVal(std::string varName, int value);     // set scalar ($varName) to integer value
	bool     setFloatVal(std::string varName, double value);     // set scalar ($varName) to double value
	bool     setStringVal(std::string varName, std::string value);     // set scalar ($varName) to string value
	bool     setArrayVal(std::string varName, string_vector &value);     // set array (@varName) to string_vector value
	bool     setHashVal(std::string varName, string_map &value);     // set hash (%varName) to CMapStringToString value
	
	// These are used to get the values of arbitrary variables ($a, $abc, @xyx, %gwxy, etc.)
	// They all return TRUE if the variable was defined and set
	bool     getIntVal(std::string varName, int &val);     // get scalar ($varName) as an int
	bool     getFloatVal(std::string varName, double &val);     // get scalar ($varName) as a double
	bool     getStringVal(std::string varName, std::string &val);     // get scalar ($varName) as a string
	bool     getArrayVal(std::string varName, string_vector &values);     // get array (@varName) as a string_vector
	bool     getHashVal(std::string varName, string_map &value);     // get hash (%varName) as a CMapStringToString
	
	// These are used to get the return value of the SCRIPT passed to doScript(). Note
	// that the return value of script is usually the value of the last line executed
	// in that script. It isn't necessarily a TRUE or FALSE or such-like.
	// This script was run in an eval() block to avoid adverse consequences if the script
	// was flawed. So these functions get the return of the eval(). See the Perl manual
	// for more details.
	int          getIntEval(void);          // result of last doScript() as an integer
	double     getFloatEval(void);          // result of last doScript() as a double
	std::string     getStringEval(void);     // result of last doScript() as a string
	
	// If the doScript() call failed, this gets the error message from Perl.
	// If doScript() succeeded, this returns an empty string. See definition of $@.
	std::string     getErrorMsg(void) const;  // last error from eval{} in doScript(), aka, $@
	
	// Normally, warnings are sent to STDERR. But that isn't very useful in a Windows
	// environment. So instead, they are saved in $__w_warnings. You can explicitly manipulate
	// that variable or use these functions to access it.
	//
	// Warnings accumulate throughout the lifetime of the Perl instance, so you may want to
	// use clearWarnings() to "start over". Or you could terminate the Perl instance and
	// start a new one. But that wastes time and you lose ALL your variables. Alternatively,
	// you can use SetclearWarningsOnScript() to automatically invoke clearWarnings() when
	// you call doScript().
	std::string getWarnings(void);     // get accumulated warnings ($__w_warnings)
	void clearWarnings(void);     // clear out accumulated warnings ($__w_warnings)
	
	bool SetfailOnWarning(bool);          // set to TRUE if warnings cause doScript() to return FALSE, returns previous setting
	bool SetclearWarningsOnScript(bool); // set to TRUE if warnings are cleared before executing a doScript(), returns previous setting
	
	// Overrides
	
	// Implementation
public:
	virtual ~CPerlWrapSTL();
};

/////////////////////////////////////////////////////////////////////////////

#endif // !defined(PERLWRAPSTL_H)

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Thales Visionix
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions