This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

| Call Function By Name Submitted by

This code illustrates how one can call a function using a string literal, or a char * this makes it very useful for in-game command consoles, or scripting languages, or whatever you want. All you have to do to call the function is
CallFunctionByName("MyFunction", args); or strcpy(funcCaller, "MyFunction");
CallFunctionByName(funcCaller, args); (For the reference: This code uses a modified version of John W. Ratcliff's StringTable class - Thanks John!) Happy Coding

Currently browsing [CallFunc.zip] (32,369 bytes) - [test.cpp] - (2,484 bytes)

    /* File:		test.cpp
     * Author(s):	Michael Deardeuff	<mr__goodbytes@hotmail.com
     * Description:
     *		Tests the CallFunctionByName Routine
     * Notes:
     *		Copyright (C) 2000 Michael Deardeuff
     *		You may use this code in anything you want as long as you keep the copyright notices intact
     */

    #ifdef _MSC_VER // >= 1200					// For MSVC++ Only (6.0+ in comments)
    #pragma warning(disable :4786)				// Disable all those pesky warnings you get
    #endif // _MSC_VER							// from using the STL

    #include <map>

    #include "mgTable.h"
    #include "function.h"
    /*
    extern "C"
    {
    StringTable functionTable;
    std::map<char *, FunctionPointer> mFunction;
    }
    */
    void FunctionTableInit();

    int main()
    {
    	FunctionTableInit();

    	bool done=false;
    	char buf[32];
    	do
    	{
    		printf("Enter name of function in function table\n");
    		printf("Or enter 'bye', 'quit', or 'end' to exit:\n");
    		printf("Currently only HoserChild and MrGoodbytes\n");
    		printf("are valid function names\n\nFunction: ");

    		// Get Function name
    		if( fgets( buf, sizeof( buf ), stdin ) == NULL )
    		{
    			done = true;
    			break;
    		}

    		// remove the trailing '\n' from string
    		strchr(buf, 10)[0] = '\0';	// isn't that ugly :C

    		String command = buf;

    		// see if user wants to quit
    		if ( command == "bye" || command == "end" || command == "quit" )
    		{
    			done = true;
    			break;
    		}
    		else
    		{
    			// enter "arguments"
    			printf("\nEnter a string to pass as an argument\nArgs: ");

    			command = buf;
    			if( fgets( buf, sizeof( buf ), stdin ) == NULL )
    			{
    				done = true;
    				break;
    			}

    			printf("\n\n-------------------------------------------\n\n");
    			if (!CallFunctionByName((char *)command.c_str(), buf))
    				printf("\n%s is not in the Callable Function Table\n\n", command.c_str());
    		}

    	} while ( !done );

    	printf("\n\n---------------------------------\n\n");
    	// Can also be called with a string literal:
    	CallFunctionByName( "MrGoodbytes", (void *)"Goodbye");

    	return 0;
    }

    // Add the functions to the list
    void FunctionTableInit()
    {
    	AddFunction("HoserChild", HoserChild);
    	AddFunction("MrGoodbytes", MrGoodbytes);
    	AddFunction("NullFunc", NULL);
    };

    /**** The User Callable Functions ********************************************/
    void HoserChild(void *args)
    {
    	printf("HoserChild says:\n%s\n", (char *)args);
    }

    void MrGoodbytes(void *args)
    {
    	printf("Mr Goodbytes' own personal function:\n%s\n", (char *)args);
    }

Currently browsing [CallFunc.zip] (32,369 bytes) - [CallFunc.cpp] - (2,967 bytes)

    /* File:		CallFunc.cpp
     * Author(s):	Michael Deardeuff <mr__goodbytes@hotmail.com>
     * Description:
     *		Implements CallFunctionByName() and AddFunction() methods
     * Notes:
     *		Copyright (C) 2000 Michael Deardeuff
     *		You may use the code in whatever you want as long as the copyright notice stays intact.
     * Usage:
     *		To use these to functions(methods if you prefer), you first add the function to the
     *		"Callable Function List" by calling AddFunction() with the name you wish to give the
     *		function, and the function itself. Then to call the function in your code, you invoke
     *		CallFunctionByName() with the name you gave the function, and any arguments you may wish.
     *		to pass to the function.
     *		Example:
     *
     *			void CallMeFunc(void *args)
     *			{
     *				// Do Something...
     *			}
     *
     *			int main()
     *			{
     *				char funcCaller = "MyFunction";	// for later
     *
     *				// Add the Function to the "Callable Function List"
     *				AddFunction("MyFunction", CallMeFunc);
     *
     *				// Call the function in a variaty of ways
     *				CallFunctionByName("MyFunction", NULL);
     *				CallFunctionByName(funcCaller, NULL);
     *
     *				// ...
     *				return 0;
     *			}
     *
     *		I find this useful when using a scripting language, or a console debugger in your game.
     *		Happy Coding!
     *		-Michael Deardeuff
     */

    #ifdef _MSC_VER // >= 1200					// For MSVC++ Only (6.0+ in comments)
    #pragma warning(disable :4786)				// Disable all those pesky warnings you get
    #endif // _MSC_VER							// from using the STL

    #include <map>

    #include "mgTable.h"
    #include "function.h"

    // For use by our "map"
    class FunctionPointer
    {
    public:
    	void (*pFunc)(void *args);
    };

    StringTable functionTable;
    std::map<char *, FunctionPointer> mFunction;

    /* CallFunctionByName():
     *	Calls a function associated with to a string name
     *	Functions must be added to callable list via AddFunctions()
     */
    bool CallFunctionByName (char * pName, void * args)
    {
    	char * result;

    	// If the name is in the list, call it;
    	if (functionTable.IsIn(pName))
    	{
    		result = (char*)functionTable.Get(pName);
    		mFunction[ result ].pFunc( args );			// this is a good thing about maps
    		return true;	//Ok
    	}
    	return false;	// Didn't happen
    }

    /* AddFunction():
     *	Adds functions and their associated strings to the list
     *	callable by CallFunctionName
     *	returns true if successful
     */
    bool AddFunction(char * pName, void (*pFunc)(void *args))
    {
    	FunctionPointer fp;
    	char * result;

    	// Test to see whether pFunc is valid, and whether
    	// pName is already listed in the set
    	if ((pFunc != NULL) && (functionTable.IsIn(pName)))
    		return false;	// Already something with that name in list

    	// Puts name in the function table
    	result = (char *) functionTable.Get(pName);

    	// Assign the function pointer to the map
    	// with the above result as the key
    	fp.pFunc = pFunc;
    	mFunction[result] = fp;

    	return true;	// Ok
    }

Currently browsing [CallFunc.zip] (32,369 bytes) - [function.h] - (520 bytes)

    #ifndef FUNCTION_H
    #define FUNCTION_H

    #ifdef _MSC_VER // >= 1200					// For MSVC++ Only (6.0+ in comments)
    #pragma warning(disable :4786)				// Disable all those pesky warnings you get
    #endif // _MSC_VER							// from using the STL

    // Defines (or includes) all callable functions for use of Call...ByName()

    bool CallFunctionByName (char * pName, void* args);
    bool AddFunction(char *pName, void (*pFunc)(void *args));

    void HoserChild(void *args);
    void MrGoodbytes(void *args);

    #endif // FUNCTION_H

Currently browsing [CallFunc.zip] (32,369 bytes) - [mgTable.cpp] - (2,172 bytes)

    /* File:		mgTable.cpp
     * Author(s):	John W. Ratcliff	<jratcliff@verant.com>
     *				Michael Deardeuff	<mr__goodbytes@hotmail.com>
     * Descripton:
     *		Implements the StringTable class. For a better description, consult "sTable.h"
     * Notes:
     *		John W. Ratcliff made about 99% of this. All thanks go to him
     *		Michael Deardeuff just added IsIn() for use of CallFunctionByName
     */

    #ifdef _MSC_VER // >= 1200					// For MSVC++ Only (6.0+ in comments)
    #pragma warning(disable :4786)				// Disable all those pesky warnings you get
    #endif // _MSC_VER							// from using the STL

    #include <string.h>
    #include <string>
    #include <set>
    #include "mgTable.h"

    // Compares two strings, returns true if first is less than second (used by std::set)
    bool CharPtrLess::operator()(const char *v1,const char *v2) const
    {
    	int v = strcmp(v1,v2);
    	if ( v < 0 )
    		return true;
    	return false;
    }

    // Clean up.
    StringTable::~StringTable(void)
    {
    	CharPtrSet::iterator i;
        for (i=mStrings.begin(); i!=mStrings.end(); i++)
        {
    		char *str = (char *)(*i);
    		delete str;
        }
    }

    /* Get():
     *	Searches the set, seeing if "str" is already in set.
     *	If so, returns a pointer to the string, If not,
     *	creates a new string, and returns a pointer to
     *	the newly allocated string;
     */
    const char * StringTable::Get(const char *str)
    {
        CharPtrSet::iterator found;

    	// Search the set for str
        found = mStrings.find( str );

    	// if found return pointer to the original string
        if ( found != mStrings.end() )
    		return (*found);

    	// create a new string identical to "str"
        int lngth = strlen(str);
        char *mem = new char[lngth+1];
        strcpy(mem,str);

    	// insert new string into the set, and return a pointer
    	mStrings.insert( mem );
    	return mem;
    }

    /* IsIn():
     *	Searches the set for occurance of "str". Returns True
     *	if found, false if not
     */
    bool StringTable::IsIn(const char *str)
    {
    	CharPtrSet::iterator found;
    	found = mStrings.find( str );
    	if (found != mStrings.end())
    		return true;
    	return false;
    }

    const char * StringTable::Get(const String &str)
    {
    	return Get( str.c_str() );
    }

Currently browsing [CallFunc.zip] (32,369 bytes) - [mgTable.h] - (4,189 bytes)

    #ifndef MR_GOODBYTES_TABLE_H
    #define MR_GOODBYTES_TABLE_H

    #ifdef _MSC_VER // >= 1200					// For MSVC++ Only (6.0+ in comments)
    #pragma warning(disable :4786)				// Disable all those pesky warnings you get
    #endif // _MSC_VER							// from using the STL

    #include <string.h>
    #include <string>
    #include <set>

    // This class implements a 'stringtable'.  It is being released into
    // the public domain on September 27, 2000 by John W. Ratcliff
    // jratcliff@verant.com for FlipCode.com as part of the 'code of they day'
    // project.
    //
    // What the heck does a 'StringTable' class do for me?  What a StringTable
    // is used for is to manage a collection of shared strings across a package.
    // It is primarily used for tokens, keywords, asset names, etc.  You do
    // *NOT* want to use the StringTable for any cases which could produce
    // an infinite number of strings.  This is only for managing a finite list
    // of keywords.
    //
    // The reason you use a string table is so that you can keep track of items
    // by ASCII name instead of some non-intutitive and arbritrary id number.
    // Normally it is not practical to make a container class who's key is
    // an STL string.  First of all there is a memory overhead, and additionally
    // there is a serious peformance penalty.  However, with the StringTable
    // class, instead you can keep track of a list of items where the key is
    // a pointer to the string, instead of the string itself.  Now you can
    // compare if 'two strings are equal' simply by comparing if their address
    // is the same.  Remember that any container class which uses this pointer as
    // a key is *NOT* in alphabetical order!!  It's ordered based on the address
    // in memory of the string itself.  But that doesn't matter, because the
    // purpose of the container is not to maintain an alphabetical list of
    // items but rather to simply locate items *BY NAME* extremely quickly.
    //
    // Using a stringtable makes it trivial to keep ASCII names and descriptions
    // as member variables in all of your classes.  This makes debugging and
    // debug output vastly simpler.
    //
    // Example: Say you contruct a new intance of a Vehicle class.  In it's
    // constructor you might have something like:
    //
    // mObjectName = gStringTable.Get("vehicle");
    //
    // Where mObjectName is a member variable of type 'const char *' and
    // gStringTable is some global instance of a shared string table across
    // your application.  Now, you can compare whether or not an object is of
    // type 'vehicle' simply by comparing it's name to anybody else's name
    // with the two pointers allocated with the same string table.
    //
    // This is extremely convenient for debugging, logging, etc.
    //
    // To create an STL map where you access every item *by name* all you
    // have to do is:
    //
    // typedef std::map< const char * , Texture *> TextureMap;
    //
    // This would create an STL map that would allow you to quickly look
    // up any texture by name.  A fairly useful data structure.
    //
    // Example of how to locate a texture by name:
    //
    // **NOTE* texname must have been created by the same StringTable
    //
    // Texture * FindTexture(const char *texname)
    // {
    //   TextureMap::iterator found; // STL map iterator to find item.
    //   found = mTextures.find( texname ); // search red/black tree
    //   if ( found != mTextures.end() ) return (*found).second;
    //   return 0; // no texture of this name found.
    // }
    //
    // The string table implementation uses STL to maintain the collection
    // of strings.  If you change the comparator function in CharPtrLess
    // from strcmp to stricmp then all of your strings will be created without
    // case sensitivity, which is often the behavior you want for tokens and
    // keywords.

    typedef std::string String;

    class CharPtrLess
    {
    public:
    	bool operator()(const char *v1,const char *v2) const;
    };

    typedef std::set< const char *, CharPtrLess > CharPtrSet;

    class StringTable
    {
    public:
    	StringTable(void){}

    	~StringTable(void);

    	const char * Get(const char *str);
    	const char * Get(const String &str);

    	bool IsIn(const char *str);

    private:
    	CharPtrSet mStrings;
    };

    #endif //MR_GOODBYTES_TABLE_H

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.