Click here to Skip to main content
15,888,521 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 215.9K   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.2
//
//	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).
//
////////////////////////////////////////////////////////////////////////////////
//
//  Copyright Notices
//  -----------------
//
//  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., or
//  SiePerl (http://www.cpan.org/ports) under the GPL/Artistic license.
//
//  Credits for the `Disclaimer' and `Terms of use' goes directly to Davide' Calabro.
//
//


#pragma once

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


#ifdef _UNICODE
#error PXPerl no longer supports Unicode compilation
#endif



namespace PXPerl
{


class CPerl;


class CPerlConfigFile
{
	friend class CPerl;
public:

	////
	// Configurarion File Creation Helpers
	// -----------------------------------

	// 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);

	// 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='~', CString *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='~');

	// 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();
	};

protected:
	CString 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 or already loaded, false otherwise.
	bool Load(void);

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


	////
	// Script compilation (parsing) functions.
	// szName : [in] an unique name to identify the script,
	//   must contain only letters and digits, mustn't start with a digit
	//		(will be used as a Perl package name).
	// All return a CScript object. Can be invalid in case of error.

	// Parses a string.
	CScript Compile(LPCSTR szName, LPCSTR szScript);

	// Parses a config file.
	CScript Compile(LPCSTR szName, const CPerlConfigFile& perlConfig);

	// Parses a RT_PERL resource.
	CScript Compile(LPCSTR szName, int nResID);

	/// Parses a file.
	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(CString &strContents);
	
	// Grabs the STDOUT output (the default output) of the interpreter.
	// [returns] true if strContents is not empty.
	bool GetSTDOUT(CString &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);


	////
	// Following functions are self explanatory I think.
	// script : [in] a valid CScript object.
	// szVariable : [in] variable name (sample: abc for scalar $abc, array @abc, hash %abc).
	// All return true if successful, false otherwise.

	// With Get* functions, in case of failure, the 'value' argument passed is not changed.

	bool SetInt(const CScript& script, LPCSTR szVariable, const int value);
	bool GetInt(const CScript& script, LPCSTR szVariable, int &value);
	bool SetFloat(const CScript& script, LPCSTR szVariable, const double value);
	bool GetFloat(const CScript& script, LPCSTR szVariable, double &value);
	bool SetString(const CScript& script, LPCSTR szVariable, LPCSTR value);
	bool GetString(const CScript& script, LPCSTR szVariable, CString &value);

	// Pass true for bAppend to append, for example,
	// the array you pass to the Perl array (SetArray).

	bool SetArray(const CScript& script, LPCSTR szVariable, const CStringArray &array,
		bool bAppend=false);
	bool GetArray(const CScript& script, LPCSTR szVariable, CStringArray &array,
		bool bAppend=false);
	bool SetHash(const CScript& script, LPCSTR szVariable, const CMapStringToString &hash,
		bool bAppend=false);
	bool GetHash(const CScript& script, LPCSTR szVariable, CMapStringToString &hash,
		bool bAppend=false);

protected:
	CArray<CString, const CString&> 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 CString 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