/********************************************************************** * test program for basic and 'ppembed' extended API calls. * this includes a "main" function: C is on top in this program. **********************************************************************/ #include #define TRACE(msg) printf("\n%s\n", msg); main(argc, argv) int argc; char **argv; { printf("Hello from C.\n"); Py_Initialize(); /* initialize embedded python libraries */ PySys_SetArgv(argc, argv); /* optional: export command args to python */ BASIC_EMBEDDING(); EMBEDDED_CALL_API(); printf("Bye from C.\n"); Py_Exit(0); /* optional: runs sys.exitfunc handler */ } BASIC_EMBEDDING() /* test low-level interfaces */ { PyObject *module, *dict, *pstack; /******************************************************************** * run code-strings in default namespace (module '__main__'); * uses embedding + extending: os/sys use C extension modules; * can call PyRun_SimpleString, PyRun_String, PyEval_CallObject.. ********************************************************************/ TRACE("SIMPLE STRINGS") PyRun_SimpleString("import sys, os"); PyRun_SimpleString("print 'Hello,', os.environ['USER'] + '.'"); PyRun_SimpleString("print 'Args: ', sys.argv"); PyRun_SimpleString("print 'Plat: ', sys.platform"); PyRun_SimpleString("print 'Path: ', sys.path[0:3], '...'"); /******************************************************************** * use the stack-type extension in embedded code; PyRun_String uses * explicit name-spaces and parse-modes; the PyRun_String results * are None, but they should really be DECREF'd and return values * should be checked for NULL (a python error/exception occurred); ********************************************************************/ TRACE("STACK EXTENSION") module = PyImport_AddModule("__main__"); /* fetch a module */ dict = PyModule_GetDict(module); /* get its __dict__ */ PyRun_String("from stacktype import *", Py_file_input, dict, dict); PyRun_String("x = Stack()", Py_file_input, dict, dict); PyRun_String("for c in 'SPAM':\n" /* multi-line */ "\tx.push(c)\n", Py_file_input, dict, dict); /* stmts okay */ PyRun_String("print x, len(x)", Py_file_input, dict, dict); /* make a new instance */ pstack = PyRun_String("Stack()", Py_eval_input, dict, dict); PyObject_Print(pstack, stdout, 0); Py_DECREF(pstack); } EMBEDDED_CALL_API() /* test ppembed enhanced wrappers */ { int i, status, result; char *strres; /* actual text is stored in python */ PyObject *pobject1, *pobject2; /* raw python objects: 'O' output codes */ /******************************************************************** * use the run_codestr wrapper like PyRun_SimpleString: * run string in module __main__ (since the module name argument is * NULL), with no result (since this is a statement: 2nd NULL arg); * also see inventory examples for dummy-module creation and use; ********************************************************************/ PP_Run_Codestr(PP_STATEMENT, "print 'Hello api world'", NULL, "", NULL); /******************************************************************** * turn on dynamic reload-on-call mode, and call a Python function in * a module file; the file can be changed between the five calls here; * calls "testapi.func(4, 8)": see testapi_c.py for equiv in Python; * note that this imports testapi in C, and adds it to sys.modules, * but doesn't add the name "testapi" to any other Python module: ********************************************************************/ TRACE("DYNAMIC RELOADING") PP_RELOAD = 1; for (i=0; i < 5; i++) { status = PP_Run_Function("testapi", "func", "i", &result, "(ii)", 4, 8); if (status == -1) { printf("Error running func\n"); PyErr_Print(); /* python stack dump */ } else printf("result => %d\n", result); if (i < 4) { printf("change testapi.py now..."); /* edit in another window */ getchar(); /* wait for a keypress */ } } /******************************************************************** * turn on dynamic debugging, run string, function, bytecode, object; * pdb stops execution as soon as the embedded code starts: set * breakponts, step through code, etc.; all run "testapi.func(4, 8)", * the Python "func" function which is defined in file testapi.py; ********************************************************************/ #define announce(test) result=-1; printf("Debug %s--type s to step...\n", test) #define showresult printf("C status, result => %d, %d\n\n", status, result) TRACE("DYNAMIC DEBUGGING") PP_RELOAD = 0; PP_DEBUG = 1; /* could do both at once */ announce("code string"); status = PP_Run_Codestr(PP_EXPRESSION, "func(4, 8)", "testapi", "i", &result); showresult; announce("module function call"); status = PP_Run_Function("testapi", "func", "i", &result, "(ii)", 4, 8); showresult; announce("compiled bytecode"); pobject1 = PP_Compile_Codestr(PP_EXPRESSION, "func(4, 8)"); status = PP_Run_Bytecode(pobject1, "testapi", "i", &result); Py_XDECREF(pobject1); showresult; /* could also fetch with "func" string in "testapi", or PP_Get_Global */ announce("direct object call"); pobject1 = PP_Load_Attribute("testapi", "func"); status = PP_Run_Known_Callable(pobject1, "i", &result, "(ii)", 4, 8); Py_XDECREF(pobject1); showresult; PP_DEBUG = 0; /******************************************************************** * a few object attribute tests: fetches sys module by name, which * was already imported in module __main__ by the basic embedding * tests; in general, return values should be checked for errors too; * the interactive command line also runs in module __main__; ********************************************************************/ TRACE("OBJECT ATTRIBUTES") PP_Run_Command_Line("check sys.version"); /* __main__ */ PP_Run_Codestr(PP_EXPRESSION, "sys", NULL, "O", &pobject1); /* .sys */ PP_Get_Member(pobject1, "version", "s", &strres); /* .version */ printf("fetched sys.version => %.50s...\n", strres); free(strres); PP_Set_Member(pobject1, "version", "s", "2.0 (2001?)"); /* change it */ PP_Run_Codestr(PP_STATEMENT, "print 'changed sys.version =>', sys.version", NULL, "", NULL); /* run sys.modules.has_key('testapi') */ PP_Get_Member(pobject1, "modules", "O", &pobject2); PP_Run_Method(pobject2, "has_key", "i", &result, "(s)", "testapi"); printf("sys.modules.has_key('testapi') result => %d\n", result); PP_Run_Method(pobject2, "has_key", "i", &result, "(s)", "nonesuch"); printf("sys.modules.has_key('nonesuch') result => %d\n", result); Py_XDECREF(pobject2); /* run sys.stdout.write('\n') */ printf("Sending text to sys.stdout.write..."); PP_Get_Member(pobject1, "stdout", "O", &pobject2); PP_Run_Method(pobject2, "write", "", NULL, "(s)", "\n"); Py_XDECREF(pobject1); /* in functions, free raw python objects */ Py_XDECREF(pobject2); /* passed out with "O" format code */ } /* plus any strings from "s" code */