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

PXPerlWrap (PXPerl, reloaded)

Rate me:
Please Sign up or sign in to vote.
3.88/5 (20 votes)
3 Nov 200411 min read 214.5K   761   44  
A comprehensive Perl embedding solution.
//
//	Class:		CPerl
//  Desc.:		A class to embed a persistent Perl interpreter in your MFC app
//
//	Compiler:	Visual C++
//	Tested on:	Visual C++ 6.0, Visual C++ .NET
//
//	Version:	1.1
//
//	Created:	13/July/2003
//	Updated:	13/July/2003
//
//	Author:		PixiGreg			mailto:pixigreg@ifrance.com
//
//	Disclaimer
//	----------
//	THIS SOFTWARE AND THE ACCOMPANYING FILES ARE DISTRIBUTED "AS IS" AND WITHOUT
//	ANY WARRANTIES WHETHER EXPRESSED OR IMPLIED. NO REPONSIBILITIES FOR POSSIBLE
//	DAMAGES OR EVEN FUNCTIONALITY CAN BE TAKEN. THE USER MUST ASSUME THE ENTIRE
//	RISK OF USING THIS SOFTWARE.
//
//	Terms of Use
//	------------
//	THIS SOFTWARE IS FREE FOR PERSONAL USE OR FREEWARE APPLICATIONS.
//	IF YOU USE THIS SOFTWARE IN COMMERCIAL OR SHAREWARE APPLICATIONS YOU
//	ARE GENTLY ASKED TO DONATE 5$ (FIVE U.S. DOLLARS) OR 5 EUROS TO THE AUTHOR,
//  USING PAYPAL (CONTACT THE AUTHOR FOR DETAILS).
//
////////////////////////////////////////////////////////////////////////////////
//
//  Important Notes
//  ---------------
//
//  Perl : Copyright 1987-2002, Larry Wall.
//
//  To write this class, I inspired from the existing class CPerlWrap
//  (http://www.codeproject.com/useritems/CPerlWrap.asp) by Harold Bamford.
//  Copied section from this class have been marked as such
//  (using <CPerlWrap>...</CPerlWrap>).
//
//  The idea of persistent interpreter has been found in the Perl doc `perlembed' ;
//  perlembed : copyright (C) 1995, 1996, 1997, 1998 Doug MacEachern and Jon Orwant.
//
//  If you're looking for a good Perl distribution that includes Perl docs, I sug-
//  gest you ActivePerl (http://www.activestate.com) from ActiveState Corp.
//
//  Credits for the `Disclaimer' and `Terms of use' goes directly to Davide' Calabro.
//
//


#pragma once

#include <afxtempl.h>
#include <shlwapi.h>


#ifndef CStringA // seemingly compiling with MS VC++ 6
#ifdef _UNICODE
#error Unicode not supported with MS Visual C++ 6
#else
typedef CString CStringA;
#endif
#endif


typedef CArray<CStringA, const CStringA&> CStringArrayA;

namespace PXPerl
{


class CPerl;


class CPerlConfigFile
{
	friend class CPerl;
public:
	// Configurarion File Creation Helpers
	// -----------------------------------

	// Gets current output (configuration file contents).
	// [returns] const string with configuration file contents.
	LPCSTR GetOutput(void)
	{
		return LPCSTR(m_strOutput);
	};

	// Appends your own stuff to current configuration file contents.
	// szText : [in] text to be appended.
	void Write(LPCSTR szText)
	{
		m_strOutput += szText;
	};

	// Empty the current configuration file contents.
	void Empty(void)
	{
		m_strOutput.Empty();
	};

	// Appends an integer type variable to current configuration file contents.
	// szVariable : [in] variable name (sample: abc for scalar $abc).
	// value : [in] value of variable.
	// szComment(optional) : [in] comment about variable.
	// pnDefault(optional) : [in] default value.
	void WriteInt(LPCSTR szVariable, int value, LPCSTR szComment=NULL,
		int *pnDefault=NULL);

	// Appends a boolean type variable to current configuration file contents.
	// szVariable : [in] variable name (sample: abc for scalar $abc).
	// value : [in] value of variable (true or false).
	// szComment(optional) : [in] comment about variable.
	// pbDefault(optional) : [in] default value.
	void WriteBool(LPCSTR szVariable, bool value, LPCSTR szComment=NULL,
		bool *pbDefault=NULL);

	// Appends a floating point type variable to current configuration file contents.
	// szVariable : [in] variable name (sample: abc for scalar $abc).
	// value : [in] value of variable.
	// szComment(optional) : [in] comment about variable.
	// pdDefault(optional) : [in] default value.
	void WriteFloat(LPCSTR szVariable, double value, LPCSTR szComment=NULL,
		double *pdDefault=NULL);

	// Appends a string type variable to current configuration file contents.
	// szVariable : [in] variable name (sample: abc for scalar $abc).
	// value : [in] value of variable.
	// szComment(optional) : [in] comment about variable.
	// cDelim(optional) : [in] string delimiter. MUST NOT BE A CHARACTER OF YOUR STRING.
	void WriteString(LPCSTR szVariable, LPCSTR value, LPCSTR szComment=NULL,
		char cDelim='~', CStringA *pstrDefault=NULL);

	// Appends a string array type variable to current configuration file contents.
	// szVariable : [in] variable name (sample: abc for array @abc).
	// array : [in] array.
	// szComment(optional) : [in] comment about variable.
	// cDelim(optional) : [in] strings delimiter. MUST NOT BE A CHARACTER OF YOUR STRINGS.
	void WriteStringArray(LPCSTR szVariable, CStringArray &array, LPCSTR szComment=NULL,
		char cDelim='~');

	// Flushes the current configuration file contents to the disk
	//  (write the contents to a file).
	// Reset the current configuration file contents. 
	// szFile : [in] path to a file.
	// bReset(optional) : [in] reset the configuration file contents (m_strOutput) ?
	bool Flush(LPCSTR szFile, bool bReset=true);

protected:
	CStringA m_strOutput;

public:
	static LPCSTR g_szOutputFormat;
	static LPCSTR g_szOutputFormatWithDefault;
};


class CScript
{
	friend class CPerl;
public:
	CScript(int nIndex=-1)
	{
		m_nIndex = nIndex;
	};

	// Tells if the script object is valid.
	bool IsValid(void)
	{
		return m_nIndex >= 0;
	};

	// Tells if the script object is invalid.
	bool IsInvalid(void)
	{
		return m_nIndex < 0;
	};

protected:
	int m_nIndex;
};


class CPerl  
{
public:
	////
	// Constructor.
	CPerl();

	// Destructor calls Unload() if you forget it.
	virtual ~CPerl();


	////
	// Loads the persistent interpreter.
	// [returns] true if successfuly loaded, false otherwise.
	bool Load(void);

	// Unloads the persistent interpreter and frees all memory.
	void Unload(void);


	////
	// Compiles a script.
	// szName : [in] an unique name to identify the script,
	//   must contain only letters and digits, mustn't start with a digit.
	// szScript : [in] the script itself.
	// [returns] a CScript object. Can be invalid in case of error.
	CScript Compile(LPCSTR szName, LPCSTR szScript);

	// Compiles a script produced by CPerlConfigFile.
	// szName : [in] an unique name to identify the script,
	//   must contain only letters and digits, mustn't start with a digit.
	// perlConfig : [in] a CPerlConfigFile object.
	// [returns] a CScript object. Can be invalid in case of error.
	CScript Compile(LPCSTR szName, const CPerlConfigFile& perlConfig);

	// Compiles a script loaded from a resource of type RT_PERL.
	// szName : [in] an unique name to identify the script,
	//   must contain only letters and digits, mustn't start with a digit.
	// nID : [in] the RT_PERL resource ID.
	// [returns] a CScript object. Can be invalid in case of error.
	CScript Compile(LPCSTR szName, int nResID);

	// Compiles a file.
	// szName : [in] an unique name to identify the script,
	//   must contain only letters and digits, mustn't start with a digit.
	// szScript : [in] a file containing a script.
	// [returns] a CScript object. Can be invalid in case of error.
	CScript CompileFile(LPCSTR szName, LPCSTR szFile);

	// Executes a compiled script.
	// script : [in] a valid CScript object.
	// [returns] true is successful, false otherwise.
	bool Exec(const CScript& script);

	// Cleans the namespace (variables plus script itself)
	//   associated with a compiled script, freeing memory associated with it.
	// Note that the script object passed is no longer valid after cleaning.
	// script : [in] a valid CScript object.
	void Clean(CScript & script);

	// DoScript/DoFile are helpers to execute a single script a single time.
	// Note that you can't access scripts variables with these methods.
	// [returns] true if successfuly run, false otherwise.
	bool DoScript(LPCSTR szScript);
	bool DoScript(const CPerlConfigFile& perlConfig);
	bool DoScript(int nResID);
	bool DoFile(LPCSTR szFile);


	////
	// Checks the STDERR output of the interpreter.
	// Useful to know if any error occured.
	// [returns] true if strContents is not empty.
	bool GetSTDERR(CStringA &strContents);
	
	// Grabs the STDOUT output (the default output) of the interpreter.
	// [returns] true if strContents is not empty.
	bool GetSTDOUT(CStringA &strContents);

	// Empties STDERR output.
	void EmptySTDERR(void);

	// Empties STDOUT output.
	void EmptySTDOUT(void);
	
	// Empties both STDERR and STDOUT outputs.
	void EmptyOutputs(void);


	// Empty outputs automatically at each Compile/Exec call ? 
	void SetAutoEmpty(bool bAuto=true)
	{
		m_bAutoEmpty = bAuto;
	};

	
	// Getting/Setting Variables Value
	// -------------------------------

	// Sets the integer value of a scalar variable.
	// script : [in] a valid CScript object.
	// szVariable : [in] variable name (sample: abc for scalar $abc).
	// value : [in] value to assign.
	// [returns] true if successful, false otherwise.
	bool SetInt(const CScript& script, LPCSTR szVariable, const int value);

	// Gets the integer value of a scalar variable.
	// script : [in] a valid CScript object.
	// szVariable : [in] variable name (sample: abc for scalar $abc).
	// value : [in] default value,
	//         [out] fetched value if variable exists.
	// [returns] true if successful, false otherwise.
	bool GetInt(const CScript& script, LPCSTR szVariable, int &value);

	// Sets the floating point value of a scalar variable.
	// script : [in] a valid CScript object.
	// szVariable : [in] variable name (sample: abc for scalar $abc).
	// value : [in] value to assign.
	// [returns] true if successful, false otherwise.
	bool SetFloat(const CScript& script, LPCSTR szVariable, const double value);

	// Gets the floating point value of a scalar variable.
	// script : [in] a valid CScript object.
	// szVariable : [in] variable name (sample: abc for scalar $abc).
	// value : [in] default value,
	//         [out] fetched value if variable exists.
	// [returns] true if successful, false otherwise.
	bool GetFloat(const CScript& script, LPCSTR szVariable, double &value);

	// Sets the string value of a scalar variable.
	// script : [in] a valid CScript object.
	// szVariable : [in] variable name (sample: abc for scalar $abc).
	// value : [in] value to assign.
	// [returns] true if successful, false otherwise.
	bool SetString(const CScript& script, LPCSTR szVariable, LPCSTR value);

	// Gets the string value of a scalar variable.
	// script : [in] a valid CScript object.
	// szVariable : [in] variable name (sample: abc for scalar $abc).
	// value : [in] default value,
	//         [out] fetched value if variable exists.
	// [returns] true if successful, false otherwise.
	bool GetString(const CScript& script, LPCSTR szVariable, CStringA &value);

#ifndef _UNICODE
	// Sets a string array.
	// script : [in] a valid CScript object.
	// szVariable : [in] variable name (sample: abc for array @abc).
	// array : [in] array to assign.
	// bAppend : [in] empty Perl array before adding items to it ?
	// [returns] true if successful, false otherwise.
	bool SetArray(const CScript& script, LPCSTR szVariable, const CStringArray &array,
		bool bAppend=false);

	// Gets a string array.
	// script : [in] a valid CScript object.
	// szVariable : [in] variable name (sample: abc for array @abc).
	// array : [in] existing array,
	//         [out] modified array with new items.
	// bAppend : [in] empty CStringArray array before adding items to it ?
	// [returns] true if successful, false otherwise.
	bool GetArray(const CScript& script, LPCSTR szVariable, CStringArray &array,
		bool bAppend=true);
#else
	// Will someone use them ?
	bool SetArray(const CScript& script, LPCSTR szVariable, const CStringArrayA &array,
		bool bAppend=false);
	bool GetArray(const CScript& script, LPCSTR szVariable, CStringArrayA &array,
		bool bAppend=true);
#endif

protected:
	CStringArrayA m_strAPackages; // Used to store package names
	int m_nMaxPackageIndex; // Somewhat upper bound of array above

	void *m_pMyPerl; // current instance of Perl (cast-ed as PerlInterpreter*)

	bool m_bAutoEmpty;

public:
	static CStringA g_strExeDir;
};


}

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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer
France France
Bouh

Comments and Discussions