Sign in to follow this  
MrDoomMaster

Unity Embedding Python into C++ Game

Recommended Posts

MrDoomMaster    103
Hi, I've done a LOT of google research in an attempt to figure out exactly how to embed Python into my C++ application via Boost.Python. While I have succeeded somewhat in this task, there are still many unanswered questions I have. I also would like a sort of "community code review" of what I have so far to make sure that I am logically setting things up correctly. As of right now, I can successfully execute a PY script file and call a function from my embedded module, named "Script". Below is the C++ source code for the embedded part:
#define BOOST_PYTHON_DEF( func ) boost::python::def( #func, func )


using namespace boost::python;

char const* PrintHelloWorld()
{
	return "Hello World!";
}

BOOST_PYTHON_MODULE(Script)
{
	BOOST_PYTHON_DEF( PrintHelloWorld );
}

void BeginPythonTest()
{
	try
	{
		if( PyImport_AppendInittab( "Script", initScript ) == -1 )
		{
			assert( 0 );
		}

		Py_Initialize();

		object mainModule = import( "__main__" );
		object dictionary = mainModule.attr( "__dict__" );

		exec_file( "pythontest.py", dictionary, dictionary );
	}

	catch( error_already_set const& err )
	{
		PyErr_Print();
	}
}

Right now to use anything in my "Script" module, I have to explicitly import it via Python. I would like C++ to import this for me, however I haven't been able to figure out how to automate this task. Below is my Python script (very simple):
import Script
print Script.PrintHelloWorld()

So, for starters, my first question is: How can I import the "Script" module from C++ so that I will have access to it from any python scripts run from my embedded Python interpreter? Thanks in advance.

Share this post


Link to post
Share on other sites
SiCrane    11839
I would rewrite your function like so:

class PyInitializer {
public:
PyInitializer() { Py_Initialize(); }
~PyInitializer() { Py_Finalize(); }
private:
PyInitializer(const PyInitializer &);
PyInitializer & operator=(const PyInitializer &);
};

int BeginPythonTest(void) {
PyInitializer py;
try {
initScript();

object main_mod = import("__main__");
object main_namespace = main_mod.attr("__dict__");
object script_mod = import("Script");
main_namespace["Script"] = script_mod;
exec_file("pythontest.py", main_namespace, main_namespace);

} catch(error_already_set) {
PyErr_Print();
throw;
}

With that you'd be able to use just

print Script.PrintHelloWorld()

as your Python script.

Share this post


Link to post
Share on other sites
MrDoomMaster    103
Thanks SiCrane.

With your help, I have come up with the following, which works perfectly:

#define BOOST_PYTHON_DEF( func ) boost::python::def( #func, func )

using namespace boost::python;

static char const* PrintHelloWorld()
{
return "Hello World!";
}

BOOST_PYTHON_MODULE(Script)
{
BOOST_PYTHON_DEF( PrintHelloWorld );
}

void BeginPythonTest()
{
try
{
Py_Initialize();

initScript();

object main = import( "__main__" );
object mainNamespace = main.attr( "__dict__" );

mainNamespace["Script"] = import( "Script" );

exec_file( "pythontest.py", mainNamespace, mainNamespace );

Py_Finalize();
}

catch( error_already_set const& err )
{
PyErr_Print();
}

catch( std::invalid_argument const& err )
{
PyErr_Print();
}
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this