Beispiel #1
0
int pyloader_unload_script(const char *name)
{
    int id;
    PyObject *script = py_get_script(name, &id);

    if (!script)
    {
        printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "%s is not loaded", name); 
        return 0;
    }

    /* PySys_WriteStdout("unload %s, script -> 0x%x\n", name, script); */
    
    pyscript_cleanup(script);

    if (PySequence_DelItem(script_modules, id) < 0)
    {
        PyErr_Print();
        printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "error unloading script %s", name); 
        return 0;
    }

    /* Probably a good time to call the garbage collecter to clean up reference cycles */
    PyGC_Collect();
    printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "unloaded script %s", name); 
    
    return 1; 
}
void qd_python_finalize(void)
{
    sys_mutex_free(ilock);
    Py_DECREF(dispatch_module);
    dispatch_module = 0;
    PyGC_Collect();
    Py_Finalize();
}
static gboolean
run_gc (CeditPluginLoaderPython *loader)
{
	while (PyGC_Collect ())
		;

	loader->priv->idle_gc = 0;
	return FALSE;
}
Beispiel #4
0
static int
hv_cli_dictof_update_new_method(NyHeapViewObject *hv, NyNodeGraphObject *rg)
{
    NyNodeSetObject *dictsowned = 0;
    PyObject **dp;
    int i, k, len;
    int result = -1;
    PyObject *lists[2] = {0, 0};
    
    /* These 2 lines are to avoid a leak in certain cases noted 30 Sep-3 Oct 2005. */
    NyNodeGraph_Clear(rg);
    PyGC_Collect();

    if (!(dictsowned = NyMutNodeSet_New())) goto err;
    if (!(lists[0] = hv_cli_dictof_get_static_types_list(hv))) goto err;
    if (!(lists[1] = hv_get_objects(hv))) goto err;
    for (k = 0; k < 2; k++) {
	PyObject *objects = lists[k];
	len = PyList_Size(objects);
	if (len == -1) /* catches eg type error */
	  goto err;
	for (i = 0; i < len; i++) {
	    PyObject *obj = PyList_GET_ITEM(objects, i);
	    dp = hv_cli_dictof_dictptr(obj);
	    if (dp && *dp) {
		if (NyNodeGraph_AddEdge(rg, *dp, obj) == -1)
		  goto err;
		if (NyNodeSet_setobj(dictsowned, *dp) == -1)
		  goto err;
	    }
	}
    }
    for (k = 0; k < 2; k++) {
	PyObject *objects = lists[k];
	len = PyList_Size(objects);
	for (i = 0; i < len; i++) {
	    PyObject *obj = PyList_GET_ITEM(objects, i);
	    if (DictofDict_Check(obj) && !NyNodeSet_hasobj(dictsowned, obj)) {
		if (NyNodeGraph_AddEdge(rg, obj, Py_None) == -1)
		  goto err;
	    }
	}
    }
    result = 0;
  err:
    Py_XDECREF(dictsowned);
    Py_XDECREF(lists[0]);
    Py_XDECREF(lists[1]);
    return result;
}
static void
cedit_python_shutdown (CeditPluginLoaderPython *loader)
{
	if (!Py_IsInitialized ())
		return;

	if (loader->priv->idle_gc != 0)
	{
		g_source_remove (loader->priv->idle_gc);
		loader->priv->idle_gc = 0;
	}

	while (PyGC_Collect ())
		;	

	Py_Finalize ();
}
static void
cedit_plugin_loader_iface_garbage_collect (CeditPluginLoader *loader)
{
	CeditPluginLoaderPython *pyloader;
	
	if (!Py_IsInitialized())
		return;

	pyloader = CEDIT_PLUGIN_LOADER_PYTHON (loader);

	/*
	 * We both run the GC right now and we schedule
	 * a further collection in the main loop.
	 */

	while (PyGC_Collect ())
		;

	if (pyloader->priv->idle_gc == 0)
		pyloader->priv->idle_gc = g_idle_add ((GSourceFunc)run_gc, pyloader);
}
Beispiel #7
0
/**
 * As freeswitch runs with a smaller than normal stack size (240K instead of the usual value .. 1 or 2 MB),
 * we must decrease the default python recursion limit accordingly.  Otherwise, python can easily blow
 * up the stack and the whole switch crashes.  See modlang-134
 */
static void set_max_recursion_depth(void)
{

	// assume that a stack frame is approximately 1K, so divide thread stack size (eg, 240K) by
	// 1K to get the approx number of stack frames we can hold before blowing up.
	int newMaxRecursionDepth = SWITCH_THREAD_STACKSIZE / 1024;

	PyObject *sysModule = PyImport_ImportModule("sys");
	PyObject *setRecursionLimit = PyObject_GetAttrString(sysModule, "setrecursionlimit");
	PyObject *recLimit = Py_BuildValue("(i)", newMaxRecursionDepth);
	PyObject *setrecursion_result = PyEval_CallObjectWithKeywords(setRecursionLimit, recLimit, (PyObject *) NULL);
	if (setrecursion_result) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set python recursion limit to %d\n", newMaxRecursionDepth);
	} else {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set recursion limit to %d\n", newMaxRecursionDepth);
		PyErr_Print();
		PyErr_Clear();
		PyRun_SimpleString("python_makes_sense");
		PyGC_Collect();
	}


}
Beispiel #8
0
void
Py_Finalize(void)
{
	PyInterpreterState *interp;
	PyThreadState *tstate;

	if (!initialized)
		return;

	/* The interpreter is still entirely intact at this point, and the
	 * exit funcs may be relying on that.  In particular, if some thread
	 * or exit func is still waiting to do an import, the import machinery
	 * expects Py_IsInitialized() to return true.  So don't say the
	 * interpreter is uninitialized until after the exit funcs have run.
	 * Note that Threading.py uses an exit func to do a join on all the
	 * threads created thru it, so this also protects pending imports in
	 * the threads created via Threading.
	 */
	call_sys_exitfunc();
	initialized = 0;

	/* Get current thread state and interpreter pointer */
	tstate = PyThreadState_GET();
	interp = tstate->interp;

	/* Disable signal handling */
	PyOS_FiniInterrupts();

	/* drop module references we saved */
	Py_XDECREF(warnings_module);
	warnings_module = NULL;

	/* Collect garbage.  This may call finalizers; it's nice to call these
	 * before all modules are destroyed.
	 * XXX If a __del__ or weakref callback is triggered here, and tries to
	 * XXX import a module, bad things can happen, because Python no
	 * XXX longer believes it's initialized.
	 * XXX     Fatal Python error: Interpreter not initialized (version mismatch?)
	 * XXX is easy to provoke that way.  I've also seen, e.g.,
	 * XXX     Exception exceptions.ImportError: 'No module named sha'
	 * XXX         in <function callback at 0x008F5718> ignored
	 * XXX but I'm unclear on exactly how that one happens.  In any case,
	 * XXX I haven't seen a real-life report of either of these.
	 */
	PyGC_Collect();
#ifdef COUNT_ALLOCS
	/* With COUNT_ALLOCS, it helps to run GC multiple times:
	   each collection might release some types from the type
	   list, so they become garbage. */
	while (PyGC_Collect() > 0)
		/* nothing */;
#endif

	/* Destroy all modules */
	PyImport_Cleanup();

	/* Collect final garbage.  This disposes of cycles created by
	 * new-style class definitions, for example.
	 * XXX This is disabled because it caused too many problems.  If
	 * XXX a __del__ or weakref callback triggers here, Python code has
	 * XXX a hard time running, because even the sys module has been
	 * XXX cleared out (sys.stdout is gone, sys.excepthook is gone, etc).
	 * XXX One symptom is a sequence of information-free messages
	 * XXX coming from threads (if a __del__ or callback is invoked,
	 * XXX other threads can execute too, and any exception they encounter
	 * XXX triggers a comedy of errors as subsystem after subsystem
	 * XXX fails to find what it *expects* to find in sys to help report
	 * XXX the exception and consequent unexpected failures).  I've also
	 * XXX seen segfaults then, after adding print statements to the
	 * XXX Python code getting called.
	 */
#if 0
	PyGC_Collect();
#endif

	/* Destroy the database used by _PyImport_{Fixup,Find}Extension */
	_PyImport_Fini();

	/* Debugging stuff */
#ifdef COUNT_ALLOCS
	dump_counts(stdout);
#endif

	PRINT_TOTAL_REFS();

#ifdef Py_TRACE_REFS
	/* Display all objects still alive -- this can invoke arbitrary
	 * __repr__ overrides, so requires a mostly-intact interpreter.
	 * Alas, a lot of stuff may still be alive now that will be cleaned
	 * up later.
	 */
	if (Py_GETENV("PYTHONDUMPREFS"))
		_Py_PrintReferences(stderr);
#endif /* Py_TRACE_REFS */

	/* Cleanup auto-thread-state */
#ifdef WITH_THREAD
	_PyGILState_Fini();
#endif /* WITH_THREAD */

	/* Clear interpreter state */
	PyInterpreterState_Clear(interp);

	/* Now we decref the exception classes.  After this point nothing
	   can raise an exception.  That's okay, because each Fini() method
	   below has been checked to make sure no exceptions are ever
	   raised.
	*/

	_PyExc_Fini();

	/* Delete current thread */
	PyThreadState_Swap(NULL);
	PyInterpreterState_Delete(interp);

	/* Sundry finalizers */
	PyMethod_Fini();
	PyFrame_Fini();
	PyCFunction_Fini();
	PyTuple_Fini();
	PyList_Fini();
	PySet_Fini();
	PyString_Fini();
	PyInt_Fini();
	PyFloat_Fini();

#ifdef Py_USING_UNICODE
	/* Cleanup Unicode implementation */
	_PyUnicode_Fini();
#endif

	/* XXX Still allocated:
	   - various static ad-hoc pointers to interned strings
	   - int and float free list blocks
	   - whatever various modules and libraries allocate
	*/

	PyGrammar_RemoveAccelerators(&_PyParser_Grammar);

#ifdef Py_TRACE_REFS
	/* Display addresses (& refcnts) of all objects still alive.
	 * An address can be used to find the repr of the object, printed
	 * above by _Py_PrintReferences.
	 */
	if (Py_GETENV("PYTHONDUMPREFS"))
		_Py_PrintReferenceAddresses(stderr);
#endif /* Py_TRACE_REFS */
#ifdef PYMALLOC_DEBUG
	if (Py_GETENV("PYTHONMALLOCSTATS"))
		_PyObject_DebugMallocStats();
#endif

	call_ll_exitfuncs();
}
Beispiel #9
0
static void eval_some_python(const char *funcname, char *args, switch_core_session_t *session, switch_stream_handle_t *stream, switch_event_t *params,
							 char **str, struct switch_py_thread *pt)
{
	PyThreadState *tstate = NULL;
	char *dupargs = NULL;
	char *argv[2] = { 0 };
	int argc;
	char *script = NULL;
	PyObject *module = NULL, *sp = NULL, *stp = NULL, *eve = NULL;
	PyObject *function = NULL;
	PyObject *arg = NULL;
	PyObject *result = NULL;
	char *p;

	if (str) {
		*str = NULL;
	}

	if (args) {
		dupargs = strdup(args);
	} else {
		return;
	}

	assert(dupargs != NULL);

	if (!(argc = switch_separate_string(dupargs, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No module name specified!\n");
		goto done;
	}

	script = strdup(switch_str_nil(argv[0]));

	if ((p = strstr(script, "::"))) {
		*p = '\0';
		p += 2;
		if (p) {
			funcname = p;
		}
	}

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Invoking py module: %s\n", script);

	tstate = PyThreadState_New(mainThreadState->interp);
	if (!tstate) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error acquiring tstate\n");
		goto done;
	}

	/* Save state in thread struct so we can terminate it later if needed */
	if (pt)
		pt->tstate = tstate;

	// swap in thread state
	PyEval_AcquireThread(tstate);
	init_freeswitch();

	// import the module
	module = PyImport_ImportModule((char *) script);
	if (!module) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error importing module\n");
		PyErr_Print();
		PyErr_Clear();
		goto done_swap_out;
	}
	// reload the module
	module = PyImport_ReloadModule(module);
	if (!module) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error reloading module\n");
		PyErr_Print();
		PyErr_Clear();
		goto done_swap_out;
	}
	// get the handler function to be called
	function = PyObject_GetAttrString(module, (char *) funcname);
	if (!function) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Module does not define %s\n", funcname);
		PyErr_Print();
		PyErr_Clear();
		goto done_swap_out;
	}

	if (session) {
		sp = mod_python_conjure_session(module, session);
	}

	if (params) {
		eve = mod_python_conjure_event(params);
	}

	if (stream) {
		stp = mod_python_conjure_stream(stream);
		if (stream->param_event) {
			eve = mod_python_conjure_event(stream->param_event);
		}
	}

	if (sp && eve && stp) {
		arg = Py_BuildValue("(OOOs)", sp, stp, eve, switch_str_nil(argv[1]));
	} else if (eve && stp) {
		arg = Py_BuildValue("(sOOs)", "na", stp, eve, switch_str_nil(argv[1]));
	} else if (eve) {
		arg = Py_BuildValue("(Os)", eve, switch_str_nil(argv[1]));
	} else if (sp) {
		arg = Py_BuildValue("(Os)", sp, switch_str_nil(argv[1]));
	} else {
		arg = Py_BuildValue("(s)", switch_str_nil(argv[1]));
	}

	// invoke the handler 
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call python script \n");
	result = PyEval_CallObjectWithKeywords(function, arg, (PyObject *) NULL);
	Py_DECREF(function);
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Finished calling python script \n");

	// check the result and print out any errors
	if (result) {
		if (str) {
			*str = strdup((char *) PyString_AsString(result));
		}
	} else if (!PyErr_ExceptionMatches(PyExc_SystemExit)) {
		// Print error, but ignore SystemExit 
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error calling python script\n");
		PyErr_Print();
		PyErr_Clear();
		PyRun_SimpleString("python_makes_sense");
		PyGC_Collect();
	}

  done_swap_out:

	if (arg) {
		Py_DECREF(arg);
	}

	if (sp) {
		Py_DECREF(sp);
	}

	if (tstate) {
		// thread state must be cleared explicitly or we'll get memory leaks
		PyThreadState_Clear(tstate);
		PyEval_ReleaseThread(tstate);
		PyThreadState_Delete(tstate);
	}

  done:

	switch_safe_free(dupargs);
	switch_safe_free(script);


}
Beispiel #10
0
int
Py_FinalizeEx(void)
{
    PyInterpreterState *interp;
    PyThreadState *tstate;
    int status = 0;

    if (!initialized)
        return status;

    wait_for_thread_shutdown();

    /* The interpreter is still entirely intact at this point, and the
     * exit funcs may be relying on that.  In particular, if some thread
     * or exit func is still waiting to do an import, the import machinery
     * expects Py_IsInitialized() to return true.  So don't say the
     * interpreter is uninitialized until after the exit funcs have run.
     * Note that Threading.py uses an exit func to do a join on all the
     * threads created thru it, so this also protects pending imports in
     * the threads created via Threading.
     */
    call_py_exitfuncs();

    /* Get current thread state and interpreter pointer */
    tstate = PyThreadState_GET();
    interp = tstate->interp;

    /* Remaining threads (e.g. daemon threads) will automatically exit
       after taking the GIL (in PyEval_RestoreThread()). */
    _Py_Finalizing = tstate;
    initialized = 0;

    /* Flush sys.stdout and sys.stderr */
    if (flush_std_files() < 0) {
        status = -1;
    }

    /* Disable signal handling */
    PyOS_FiniInterrupts();

    /* Collect garbage.  This may call finalizers; it's nice to call these
     * before all modules are destroyed.
     * XXX If a __del__ or weakref callback is triggered here, and tries to
     * XXX import a module, bad things can happen, because Python no
     * XXX longer believes it's initialized.
     * XXX     Fatal Python error: Interpreter not initialized (version mismatch?)
     * XXX is easy to provoke that way.  I've also seen, e.g.,
     * XXX     Exception exceptions.ImportError: 'No module named sha'
     * XXX         in <function callback at 0x008F5718> ignored
     * XXX but I'm unclear on exactly how that one happens.  In any case,
     * XXX I haven't seen a real-life report of either of these.
     */
    PyGC_Collect();
#ifdef COUNT_ALLOCS
    /* With COUNT_ALLOCS, it helps to run GC multiple times:
       each collection might release some types from the type
       list, so they become garbage. */
    while (PyGC_Collect() > 0)
        /* nothing */;
#endif
    /* Destroy all modules */
    PyImport_Cleanup();

    /* Flush sys.stdout and sys.stderr (again, in case more was printed) */
    if (flush_std_files() < 0) {
        status = -1;
    }

    /* Collect final garbage.  This disposes of cycles created by
     * class definitions, for example.
     * XXX This is disabled because it caused too many problems.  If
     * XXX a __del__ or weakref callback triggers here, Python code has
     * XXX a hard time running, because even the sys module has been
     * XXX cleared out (sys.stdout is gone, sys.excepthook is gone, etc).
     * XXX One symptom is a sequence of information-free messages
     * XXX coming from threads (if a __del__ or callback is invoked,
     * XXX other threads can execute too, and any exception they encounter
     * XXX triggers a comedy of errors as subsystem after subsystem
     * XXX fails to find what it *expects* to find in sys to help report
     * XXX the exception and consequent unexpected failures).  I've also
     * XXX seen segfaults then, after adding print statements to the
     * XXX Python code getting called.
     */
#if 0
    PyGC_Collect();
#endif

    /* Disable tracemalloc after all Python objects have been destroyed,
       so it is possible to use tracemalloc in objects destructor. */
    _PyTraceMalloc_Fini();

    /* Destroy the database used by _PyImport_{Fixup,Find}Extension */
    _PyImport_Fini();

    /* Cleanup typeobject.c's internal caches. */
    _PyType_Fini();

    /* unload faulthandler module */
    _PyFaulthandler_Fini();

    /* Debugging stuff */
#ifdef COUNT_ALLOCS
    dump_counts(stderr);
#endif
    /* dump hash stats */
    _PyHash_Fini();

    _PY_DEBUG_PRINT_TOTAL_REFS();

#ifdef Py_TRACE_REFS
    /* Display all objects still alive -- this can invoke arbitrary
     * __repr__ overrides, so requires a mostly-intact interpreter.
     * Alas, a lot of stuff may still be alive now that will be cleaned
     * up later.
     */
    if (Py_GETENV("PYTHONDUMPREFS"))
        _Py_PrintReferences(stderr);
#endif /* Py_TRACE_REFS */

    /* Clear interpreter state and all thread states. */
    PyInterpreterState_Clear(interp);

    /* Now we decref the exception classes.  After this point nothing
       can raise an exception.  That's okay, because each Fini() method
       below has been checked to make sure no exceptions are ever
       raised.
    */

    _PyExc_Fini();

    /* Sundry finalizers */
    PyMethod_Fini();
    PyFrame_Fini();
    PyCFunction_Fini();
    PyTuple_Fini();
    PyList_Fini();
    PySet_Fini();
    PyBytes_Fini();
    PyByteArray_Fini();
    PyLong_Fini();
    PyFloat_Fini();
    PyDict_Fini();
    PySlice_Fini();
    _PyGC_Fini();
    _PyRandom_Fini();
    _PyArg_Fini();

    /* Cleanup Unicode implementation */
    _PyUnicode_Fini();

    /* reset file system default encoding */
    if (!Py_HasFileSystemDefaultEncoding && Py_FileSystemDefaultEncoding) {
        PyMem_RawFree((char*)Py_FileSystemDefaultEncoding);
        Py_FileSystemDefaultEncoding = NULL;
    }

    /* XXX Still allocated:
       - various static ad-hoc pointers to interned strings
       - int and float free list blocks
       - whatever various modules and libraries allocate
    */

    PyGrammar_RemoveAccelerators(&_PyParser_Grammar);

    /* Cleanup auto-thread-state */
#ifdef WITH_THREAD
    _PyGILState_Fini();
#endif /* WITH_THREAD */

    /* Delete current thread. After this, many C API calls become crashy. */
    PyThreadState_Swap(NULL);

    PyInterpreterState_Delete(interp);

#ifdef Py_TRACE_REFS
    /* Display addresses (& refcnts) of all objects still alive.
     * An address can be used to find the repr of the object, printed
     * above by _Py_PrintReferences.
     */
    if (Py_GETENV("PYTHONDUMPREFS"))
        _Py_PrintReferenceAddresses(stderr);
#endif /* Py_TRACE_REFS */
#ifdef WITH_PYMALLOC
    if (_PyMem_PymallocEnabled()) {
        char *opt = Py_GETENV("PYTHONMALLOCSTATS");
        if (opt != NULL && *opt != '\0')
            _PyObject_DebugMallocStats(stderr);
    }
#endif

    call_ll_exitfuncs();
    return status;
}
Beispiel #11
0
void real_from_python(char* function, int* function_len,
                        double* t,  
                        double* result, int* stat)
{
#ifndef HAVE_PYTHON
  int i;
  strncpy(function, "No Python support!\n", (size_t) *function_len);
  for (i=0; i < *function_len; i++)
  {
    if (function[i] == '\0')
      function[i] = ' ';
  }
  *stat=1;
  return;
#else
  PyObject *pMain, *pGlobals, *pLocals, *pFunc, *pCode, *pResult, 
    *pArgs, *pT;
  
  char *function_c;
  
  // the function string passed down from Fortran needs terminating,
  // so make a copy and fiddle with it (remember to free it)
  function_c = (char *)malloc(*function_len+3);
  memcpy( function_c, function, *function_len );
  function_c[*function_len] = 0;

  // Get a reference to the main module and global dictionary
  pMain = PyImport_AddModule("__main__");

  pGlobals = PyModule_GetDict(pMain);
  // Global and local namespace dictionaries for our code.
  pLocals=PyDict_New();
  
  // Execute the user's code.
  pCode=PyRun_String(function_c, Py_file_input, pGlobals, pLocals);

  // Extract the function from the code.
  pFunc=PyDict_GetItemString(pLocals, "val");

  // Clean up memory from null termination.
  free(function_c);
  
  // Check for errors in executing user code.
  if (PyErr_Occurred()){
    PyErr_Print();
    *stat=1;
    return;
  }

  // Python form of time variable.
  pT=PyFloat_FromDouble(*t);

  // Tuple of arguments to function;
  pArgs=PyTuple_New(1);
  PyTuple_SetItem(pArgs, 0, pT);

  // Check for a Python error in the function call
  if (PyErr_Occurred()){
    PyErr_Print();
    *stat=1;
    return;
  }

  pResult=PyObject_CallObject(pFunc, pArgs); 
  
  // Check for a Python error in the function call
  if (PyErr_Occurred()){
    PyErr_Print();
    *stat=1;
    return;
  }

  *result = PyFloat_AsDouble(pResult);

  // Check for a Python error in result.
  if (PyErr_Occurred()){
    PyErr_Print();
    *stat=1;
    return;
  }

  Py_DECREF(pResult);  
  
  // Clean up
  Py_DECREF(pArgs);  
  Py_DECREF(pLocals);  
  Py_DECREF(pCode);  

  // Force a garbage collection
  PyGC_Collect();


  *stat=0;
  return;
#endif
}
Beispiel #12
0
void set_tensor_field_from_python(char *function, int *function_len, int *dim, 
                                  int *nodes, 
                                  double x[], double y[], double z[], double *t, 
                                  int result_dim[], 
                                  double result[], int* stat)
{
#ifndef HAVE_NUMPY
  int i;
  strncpy(function, "No Numpy support!\n", (size_t) *function_len);
  for (i=0; i < *function_len; i++)
  {
    if (function[i] == '\0')
      function[i] = ' ';
  }
  *stat=1;
  return;
#else
  PyObject *pMain, *pGlobals, *pLocals, *pFunc, *pCode, *pResult, 
    *pArgs, *pPos, *px, *pT;
  PyArrayObject *pArray;
  char *function_c;
  int i, ii, jj;

  import_array()
  
  // the function string passed down from Fortran needs terminating,
  // so make a copy and fiddle with it (remember to free it)
  function_c = (char *)malloc(*function_len+3);
  memcpy( function_c, function, *function_len );
  function_c[*function_len] = 0;
  
  // Get a reference to the main module and global dictionary
  pMain = PyImport_AddModule("__main__");
  pGlobals = PyModule_GetDict(pMain);
  // Global and local namespace dictionaries for our code.
  pLocals=PyDict_New();
  
  // Execute the user's code.
  pCode=PyRun_String(function_c, Py_file_input, pGlobals, pLocals);
  
  // Extract the function from the code.
  pFunc=PyDict_GetItemString(pLocals, "val");
  
  // Clean up memory from null termination.
  free(function_c);
  
  // Check for errors in executing user code.
  if (PyErr_Occurred()){
    PyErr_Print();
    *stat=1;
    return;
  }
  
  // Python form of time variable.
  pT=PyFloat_FromDouble(*t);
  
  // Tuple containing the current position vector.
  pPos=PyTuple_New(*dim);
  
  // Tuple of arguments to function;
  pArgs=PyTuple_New(2);
  PyTuple_SetItem(pArgs, 1, pT);
  PyTuple_SetItem(pArgs, 0, pPos);
  
  // Check for a Python error in the function call
  if (PyErr_Occurred()){
    PyErr_Print();
    *stat=1;
    return;
  }
  
  for (i = 0; i < *nodes; i++){
    px=PyFloat_FromDouble(x[i]);
    PyTuple_SetItem(pPos, 0, px);    
    
    if (*dim>1) {
      px=PyFloat_FromDouble(y[i]);
      PyTuple_SetItem(pPos, 1, px);
      
      if (*dim>2) {
        px=PyFloat_FromDouble(z[i]);
        PyTuple_SetItem(pPos, 2, px);
      }
    }
  
    pResult=PyObject_CallObject(pFunc, pArgs); 
    
    // Check for a Python error in the function call
    if (PyErr_Occurred()){
      PyErr_Print();
      *stat=1;
      return;
    }
    
    pArray = (PyArrayObject *)
      PyArray_ContiguousFromObject(pResult, PyArray_DOUBLE, 2, 2);

    if (PyErr_Occurred()){
      PyErr_Print();
      *stat=1;
      return;
    }

    if (pArray->dimensions[0] != result_dim[0] || pArray->dimensions[1] != result_dim[1])
    {
      fprintf(stderr, "Error: dimensions of array returned from python ([%d, %d]) do not match allocated dimensions of the tensor_field ([%d, %d])).\n", 
             (int) pArray->dimensions[0], (int) pArray->dimensions[1], result_dim[0], result_dim[1]);
      *stat=1;
      return;
    }

    for (ii = 0; ii < result_dim[0]; ii++){
      for (jj = 0; jj < result_dim[1]; jj++){
        
        // Note the transpose for fortran.
        double tmp;
        tmp = *(double*)(pArray->data + ii * pArray->strides[0] + jj * pArray->strides[1]);
        result[i*(result_dim[0] * result_dim[1]) + jj * result_dim[0] + ii] = tmp;
      }
    }

    Py_DECREF(pArray);

    if (PyErr_Occurred()){
      PyErr_Print();
      *stat=1;
      return;
    }
    
    Py_DECREF(pResult);  
  }
  
  // Clean up
  Py_DECREF(pArgs);  
  Py_DECREF(pLocals);  
  Py_DECREF(pCode);  
  
  // Force a garbage collection
  PyGC_Collect();
  
  *stat=0;
  return;
#endif
}
Beispiel #13
0
void set_vector_field_from_python(char *function, int *function_len, int *dim, 
                                  int *nodes, 
                                  double x[], double y[], double z[], double *t, 
                                  int *result_dim, 
                                  double result_x[], double result_y[], 
                                  double result_z[], int* stat)
{
#ifndef HAVE_PYTHON
  int i;
  strncpy(function, "No Python support!\n", (size_t) *function_len);
  for (i=0; i < *function_len; i++)
  {
    if (function[i] == '\0')
      function[i] = ' ';
  }
  *stat=1;
  return;
#else
  PyObject *pMain, *pGlobals, *pLocals, *pFunc, *pCode, *pResult, 
    *pArgs, *pPos, *px, *pT;
  char *function_c;
  int i;
  
  // the function string passed down from Fortran needs terminating,
  // so make a copy and fiddle with it (remember to free it)
  function_c = (char *)malloc(*function_len+3);
  memcpy( function_c, function, *function_len );
  function_c[*function_len] = 0;
  
  // Get a reference to the main module and global dictionary
  pMain = PyImport_AddModule("__main__");
  pGlobals = PyModule_GetDict(pMain);
  // Global and local namespace dictionaries for our code.
  pLocals=PyDict_New();
  
  // Execute the user's code.
  pCode=PyRun_String(function_c, Py_file_input, pGlobals, pLocals);
  
  // Extract the function from the code.
  pFunc=PyDict_GetItemString(pLocals, "val");
  
  // Clean up memory from null termination.
  free(function_c);
  
  // Check for errors in executing user code.
  if (PyErr_Occurred()){
    PyErr_Print();
    *stat=1;
    return;
  }
  
  // Python form of time variable.
  pT=PyFloat_FromDouble(*t);
  
  // Tuple containing the current position vector.
  pPos=PyTuple_New(*dim);
  
  // Tuple of arguments to function;
  pArgs=PyTuple_New(2);
  PyTuple_SetItem(pArgs, 1, pT);
  PyTuple_SetItem(pArgs, 0, pPos);
  
  // Check for a Python error in the function call
  if (PyErr_Occurred()){
    PyErr_Print();
    *stat=1;
    return;
  }
  
  for (i = 0; i < *nodes; i++){
    px=PyFloat_FromDouble(x[i]);
    PyTuple_SetItem(pPos, 0, px);    
    
    if (*dim>1) {
      px=PyFloat_FromDouble(y[i]);
      PyTuple_SetItem(pPos, 1, px);
      
      if (*dim>2) {
        px=PyFloat_FromDouble(z[i]);
        PyTuple_SetItem(pPos, 2, px);
      }
    }
    
    pResult=PyObject_CallObject(pFunc, pArgs);
    // Check for a Python error in the function call
    if (PyErr_Occurred()){
      PyErr_Print();
      *stat=1;
      return;
    }

    if (PyObject_Length(pResult) != *result_dim)
    {
      fprintf(stderr, "Error: length of object returned from python (%d) does not match the allocated dimension of the vector field (%d).\n",
              (int) PyObject_Length(pResult), *result_dim);
      *stat = 1;
      return;
    }
    
    
    px=PySequence_GetItem(pResult, 0);
    
    result_x[i]=PyFloat_AsDouble(px);
    // Check for a Python error in unpacking tuple.
    if (PyErr_Occurred()){
      PyErr_Print();
      *stat=1;
      return;
    }
    Py_DECREF(px);
    
    if (*result_dim>1) { 
      px=PySequence_GetItem(pResult, 1);  
      result_y[i]=PyFloat_AsDouble(px);  
      // Check for a Python error in unpacking tuple.  
      if (PyErr_Occurred()){  
         PyErr_Print();  
         return;  
      }  
      
      Py_DECREF(px);  
      if (*result_dim>2) {  
        px=PySequence_GetItem(pResult, 2);  
        result_z[i]=PyFloat_AsDouble(px);  
      // Check for a Python error in unpacking tuple.  
       if (PyErr_Occurred()){  
          PyErr_Print();  
          return;  
       }  
        Py_DECREF(px);  
      } 
    }  
    
    Py_DECREF(pResult);  
  }
  
  // Clean up
  Py_DECREF(pArgs);  
  Py_DECREF(pLocals);  
  Py_DECREF(pCode);  
  
  // Force a garbage collection
  PyGC_Collect();
  
  *stat=0;
  return;
#endif
}