OverviewFilesCommitsIssuesDocsReleasesPeers

opencog-atomspace / examples / c++-guile / PrimitiveExample.cc

97 lines · cc ref:
/*
 * PrimitiveExample.cc
 *
 * Example code showing how wrap C++ methods so that they can
 * be called from scheme.
 */

#include <opencog/atomspace/AtomSpace.h>
#include <opencog/atoms/base/Node.h>
#include <opencog/guile/SchemeEval.h>
#include <opencog/guile/SchemePrimitive.h>

using namespace opencog;

// Some example class
class MyTestClass
{
	private:
		AtomSpacePtr _as;
		int _id;  // some value in the instance
	public:

		MyTestClass(AtomSpacePtr as, int id) : _as(as), _id(id) {}

		// An example method -- accepts a handle, and wraps it
		// with a ListLink.
		Handle my_func(Handle h)
		{
			Handle hlist;
			Type t = h->get_type();
			if (nameserver().isA(t, NODE))
			{
				NodePtr n = NodeCast(h);
				std::string name = n->get_name();
				printf("Info: my_func instance %d received the node: %s\n",
				       _id, name.c_str());
				hlist = _as->add_link(LIST_LINK, h);
			}
			else
			{
				printf("Warning: my_func instance %d called with invalid handle\n", _id);
			}
			return hlist;
		}

		Handle my_other_func(Handle h)
		{
			throw RuntimeException(TRACE_INFO, "I threw an exception %d", _id);
			return Handle::UNDEFINED;
		}
};

int main ()
{
	// Need to access the atomspace to get it to initialize itself.
	AtomSpacePtr as = createAtomSpace();

	// Do this early, so that guile is initialized.
	SchemeEval* eval = SchemeEval::get_scheme_evaluator(as);

	printf("\nInfo: Start creating a scheme call into C++\n");

	// Create the example class, and define a scheme function,
	// named "bingo", that will call one of its methods
	MyTestClass *mtc = new MyTestClass(as, 42);
	define_scheme_primitive("bingo", &MyTestClass::my_func, mtc);

	// Now, call bingo, with a reasonable argument. Since
	// MyTestClass::my_func is expecting a handle, we better pass
	// bingo a handle.
	eval->eval("(define nnn (cog-new-node 'ConceptNode \"Hello World!\"))");
	std::string rslt = eval->eval("(bingo nnn)");
	if (eval->eval_error())
	{
		printf("Error: failed evaluation\n");
	}

	// Print the result of calling MyTestClass::my_func
	printf("Info: Result of scheme evaluation is %s", rslt.c_str());

	// Now try throwing an exception.
	define_scheme_primitive("whoops", &MyTestClass::my_other_func, mtc);

	rslt = eval->eval("(whoops nnn)");
	if (!eval->eval_error())
	{
		printf("XXX ERROR XXX: an error should have been thrown, but wasn't!\n");
	}

	// Print the result of calling MyTestClass::my_func
	printf("Info: Intentional throw gave the following output:\n%s", rslt.c_str());

	printf("\nInfo: The big stack trace above is intentional!\n");
	printf("\nInfo: We are done, bye!\n");
	return  0;
}