[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [35005] trunk/blender: Experimental option to build blender as a python module, rather then blender embedding python.

Campbell Barton ideasman42 at gmail.com
Mon Feb 21 00:39:29 CET 2011


Revision: 35005
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=35005
Author:   campbellbarton
Date:     2011-02-20 23:39:29 +0000 (Sun, 20 Feb 2011)
Log Message:
-----------
Experimental option to build blender as a python module, rather then blender embedding python.
CMake build option WITH_PYTHON_MODULE, will build ./bin/bpy.so

This allows 'bpy' to be imported from python or other applications/IDE's which embed python, eg:
   python -c "import bpy ; bpy.ops.render.render(write_still=True)"

This runs in background mode and has similar restrictions to running a script:
   blender --background --python test.py

TODO:
 - install to site-packages with blender scripts
 - add support for imp.reload()

Modified Paths:
--------------
    trunk/blender/CMakeLists.txt
    trunk/blender/build_files/cmake/macros.cmake
    trunk/blender/source/blender/editors/render/render_internal.c
    trunk/blender/source/blender/python/intern/CMakeLists.txt
    trunk/blender/source/blender/python/intern/bpy.c
    trunk/blender/source/blender/python/intern/bpy.h
    trunk/blender/source/blender/python/intern/bpy_interface.c
    trunk/blender/source/creator/CMakeLists.txt
    trunk/blender/source/creator/creator.c

Modified: trunk/blender/CMakeLists.txt
===================================================================
--- trunk/blender/CMakeLists.txt	2011-02-20 23:21:15 UTC (rev 35004)
+++ trunk/blender/CMakeLists.txt	2011-02-20 23:39:29 UTC (rev 35005)
@@ -69,6 +69,7 @@
 # Blender internal features
 option(WITH_INTERNATIONAL "Enable I18N   (International fonts and text)" ON)
 option(WITH_PYTHON        "Enable Embedded Python API" ON)
+option(WITH_PYTHON_MODULE "Enable building as a python module (experemental)" OFF)
 option(WITH_BUILDINFO     "Include extra build details" ON)
 option(WITH_IK_ITASC      "Enable ITASC IK solver" ON)
 option(WITH_FFTW3         "Enable FFTW3 support (Used for smoke and audio effects)" OFF)
@@ -1038,6 +1039,9 @@
 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PLATFORM_CFLAGS} ${C_WARNINGS}")
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PLATFORM_CFLAGS} ${CXX_WARNINGS}")
 
+#-------------------------------------------------------------------------------
+# Global Defines
+
 # better not define flags here but this is a debugging option thats off by default.
 if(WITH_CXX_GUARDEDALLOC)
 	set(CMAKE_CXX_FLAGS " -DWITH_CXX_GUARDEDALLOC -I${CMAKE_SOURCE_DIR}/intern/guardedalloc ${CMAKE_CXX_FLAGS}")

Modified: trunk/blender/build_files/cmake/macros.cmake
===================================================================
--- trunk/blender/build_files/cmake/macros.cmake	2011-02-20 23:21:15 UTC (rev 35004)
+++ trunk/blender/build_files/cmake/macros.cmake	2011-02-20 23:39:29 UTC (rev 35005)
@@ -66,7 +66,7 @@
 
 	link_directories(${JPEG_LIBPATH} ${PNG_LIBPATH} ${ZLIB_LIBPATH} ${FREETYPE_LIBPATH})
 
-	if(WITH_PYTHON)
+	if(WITH_PYTHON AND NOT WITH_PYTHON_MODULE)
 		link_directories(${PYTHON_LIBPATH})
 	endif()
 	if(WITH_INTERNATIONAL)
@@ -127,7 +127,7 @@
 	target_link_libraries(${target} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} ${LLIBS})
 
 	# since we are using the local libs for python when compiling msvc projects, we need to add _d when compiling debug versions
-	if(WITH_PYTHON)
+	if(WITH_PYTHON AND NOT WITH_PYTHON_MODULE)
 		target_link_libraries(${target} ${PYTHON_LINKFLAGS})
 
 		if(WIN32 AND NOT UNIX)

Modified: trunk/blender/source/blender/editors/render/render_internal.c
===================================================================
--- trunk/blender/source/blender/editors/render/render_internal.c	2011-02-20 23:21:15 UTC (rev 35004)
+++ trunk/blender/source/blender/editors/render/render_internal.c	2011-02-20 23:39:29 UTC (rev 35005)
@@ -800,7 +800,7 @@
 	ot->modal= screen_render_modal;
 	ot->exec= screen_render_exec;
 
-	ot->poll= ED_operator_screenactive;
+	/*ot->poll= ED_operator_screenactive;*/ /* this isnt needed, causes failer in background mode */
 
 	RNA_def_boolean(ot->srna, "animation", 0, "Animation", "Render files from the animation range of this scene");
 	RNA_def_boolean(ot->srna, "write_still", 0, "Write Image", "Save rendered the image to the output path (used only when animation is disabled)");

Modified: trunk/blender/source/blender/python/intern/CMakeLists.txt
===================================================================
--- trunk/blender/source/blender/python/intern/CMakeLists.txt	2011-02-20 23:21:15 UTC (rev 35004)
+++ trunk/blender/source/blender/python/intern/CMakeLists.txt	2011-02-20 23:39:29 UTC (rev 35005)
@@ -67,4 +67,8 @@
 	add_definitions(-DBUILD_DATE)
 endif()
 
+if(WITH_PYTHON_MODULE)
+	add_definitions(-DWITH_PYTHON_MODULE)
+endif()
+
 blender_add_lib(bf_python "${SRC}" "${INC}")

Modified: trunk/blender/source/blender/python/intern/bpy.c
===================================================================
--- trunk/blender/source/blender/python/intern/bpy.c	2011-02-20 23:21:15 UTC (rev 35004)
+++ trunk/blender/source/blender/python/intern/bpy.c	2011-02-20 23:39:29 UTC (rev 35005)
@@ -53,6 +53,8 @@
 
 #include "AUD_PyInit.h"
 
+PyObject *bpy_package_py= NULL;
+
 static char bpy_script_paths_doc[] =
 ".. function:: script_paths()\n"
 "\n"
@@ -161,7 +163,7 @@
 static PyMethodDef meth_bpy_blend_paths = {"blend_paths", (PyCFunction)bpy_blend_paths, METH_VARARGS|METH_KEYWORDS, bpy_blend_paths_doc};
 static PyMethodDef meth_bpy_user_resource = {"user_resource", (PyCFunction)bpy_user_resource, METH_VARARGS|METH_KEYWORDS, NULL};
 
-static void bpy_import_test(const char *modname)
+static PyObject *bpy_import_test(const char *modname)
 {
 	PyObject *mod= PyImport_ImportModuleLevel((char *)modname, NULL, NULL, NULL, 0);
 	if(mod) {
@@ -170,7 +172,9 @@
 	else {
 		PyErr_Print();
 		PyErr_Clear();
-	}	
+	}
+
+	return mod;
 }
 
 /*****************************************************************************
@@ -235,5 +239,5 @@
 	PyModule_AddObject(mod, meth_bpy_unregister_class.ml_name, (PyObject *)PyCFunction_New(&meth_bpy_unregister_class, NULL));
 
 	/* add our own modules dir, this is a python package */
-	bpy_import_test("bpy");
+	bpy_package_py= bpy_import_test("bpy");
 }

Modified: trunk/blender/source/blender/python/intern/bpy.h
===================================================================
--- trunk/blender/source/blender/python/intern/bpy.h	2011-02-20 23:21:15 UTC (rev 35004)
+++ trunk/blender/source/blender/python/intern/bpy.h	2011-02-20 23:39:29 UTC (rev 35005)
@@ -22,4 +22,4 @@
  * ***** END GPL LICENSE BLOCK ***** */
  
 void BPy_init_modules( void );
- 
+extern PyObject *bpy_package_py;

Modified: trunk/blender/source/blender/python/intern/bpy_interface.c
===================================================================
--- trunk/blender/source/blender/python/intern/bpy_interface.c	2011-02-20 23:21:15 UTC (rev 35004)
+++ trunk/blender/source/blender/python/intern/bpy_interface.c	2011-02-20 23:39:29 UTC (rev 35005)
@@ -157,6 +157,7 @@
 }
 
 /* must be called before Py_Initialize */
+#ifndef WITH_PYTHON_MODULE
 static void bpy_python_start_path(void)
 {
 	char *py_path_bundle= BLI_get_folder(BLENDER_PYTHON, NULL);
@@ -195,9 +196,8 @@
 		// printf("found python (wchar_t) '%ls'\n", py_path_bundle_wchar);
 	}
 }
+#endif
 
-
-
 void BPY_context_set(bContext *C)
 {
 	BPy_SetContext(C);
@@ -219,8 +219,9 @@
 /* call BPY_context_set first */
 void BPY_python_start(int argc, const char **argv)
 {
+#ifndef WITH_PYTHON_MODULE
 	PyThreadState *py_tstate = NULL;
-	
+
 	/* not essential but nice to set our name */
 	static wchar_t bprogname_wchar[FILE_MAXDIR+FILE_MAXFILE]; /* python holds a reference */
 	utf8towchar(bprogname_wchar, bprogname);
@@ -252,8 +253,13 @@
 	
 	/* Initialize thread support (also acquires lock) */
 	PyEval_InitThreads();
+#else
+	(void)argc;
+	(void)argv;
 	
-	
+	PyImport_ExtendInittab(bpy_internal_modules);
+#endif
+
 	/* bpy.* and lets us import it */
 	BPy_init_modules();
 
@@ -281,8 +287,10 @@
 	
 	pyrna_alloc_types();
 
+#ifndef WITH_PYTHON_MODULE
 	py_tstate = PyGILState_GetThisThreadState();
 	PyEval_ReleaseThread(py_tstate);
+#endif
 }
 
 void BPY_python_end(void)
@@ -659,3 +667,51 @@
 	return done;
 }
 
+
+#ifdef WITH_PYTHON_MODULE
+/* TODO, reloading the module isnt functional at the moment. */
+
+extern int main_python(int argc, const char **argv);
+static struct PyModuleDef bpy_proxy_def = {
+	PyModuleDef_HEAD_INIT,
+	"bpy",  /* m_name */
+	NULL,  /* m_doc */
+	0,  /* m_size */
+	NULL,  /* m_methods */
+	NULL,  /* m_reload */
+	NULL,  /* m_traverse */
+	NULL,  /* m_clear */
+	NULL,  /* m_free */
+};	
+
+PyMODINIT_FUNC
+PyInit_bpy(void)
+{
+	int argc= 0;
+	const char *argv[]={NULL};
+	
+	main_python(argc, argv);
+
+	/* initialized in BPy_init_modules() */
+	if(bpy_package_py) {
+		/* Problem:
+		 * 1) this init function is expected to have a private member defined - 'md_def'
+		 *    but this is only set for C defined modules (not py packages)
+		 *    so we cant return 'bpy_package_py' as is.
+		 *
+		 * 2) there is a 'bpy' C module for python to load which is basically all of blender,
+		 *    and there is scripts/bpy/__init__.py, 
+		 *    we may end up having to rename this module so there is no naming conflict here eg:
+		 *    'from blender import bpy' */
+		PyObject *bpy_proxy= PyModule_Create(&bpy_proxy_def);
+		PyDict_Update(PyModule_GetDict(bpy_proxy), PyModule_GetDict(bpy_package_py));
+		return bpy_proxy;
+	}
+	else {
+		PyErr_SetString(PyExc_RuntimeError, "could not import internal bpy package");
+		return NULL;
+	}
+	
+	
+}
+#endif

Modified: trunk/blender/source/creator/CMakeLists.txt
===================================================================
--- trunk/blender/source/creator/CMakeLists.txt	2011-02-20 23:21:15 UTC (rev 35004)
+++ trunk/blender/source/creator/CMakeLists.txt	2011-02-20 23:39:29 UTC (rev 35005)
@@ -127,8 +127,21 @@
 endif()
 
 # message(STATUS "Configuring blender")
+if(WITH_PYTHON_MODULE)
+	add_definitions(-DWITH_PYTHON_MODULE)
 
-add_executable(blender ${EXETYPE} ${SRC})
+	# creates ./bin/bpy.so which can be imported as a python module.
+	add_library(blender SHARED ${SRC})
+	set_target_properties(
+		blender
+		PROPERTIES
+			 PREFIX ""
+			 OUTPUT_NAME bpy
+			 LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/
+	)
+else()
+	add_executable(blender ${EXETYPE} ${SRC})
+endif()
 
 # Post build steps for bundling/packaging.
 

Modified: trunk/blender/source/creator/creator.c
===================================================================
--- trunk/blender/source/creator/creator.c	2011-02-20 23:21:15 UTC (rev 35004)
+++ trunk/blender/source/creator/creator.c	2011-02-20 23:39:29 UTC (rev 35005)
@@ -154,6 +154,7 @@
 }
 #endif
 
+#ifdef WITH_PYTHON_MODULE
 /* handling ctrl-c event in console */
 static void blender_esc(int sig)
 {
@@ -170,6 +171,7 @@
 		count++;
 	}
 }
+#endif
 
 /* buildinfo can have quotes */
 #ifdef BUILD_DATE
@@ -1111,12 +1113,21 @@
 
 }
 
-int main(int argc, char **argv)
+#ifdef WITH_PYTHON_MODULE
+/* allow python module to call main */
+#define main main_python
+#endif
+
+int main(int argc, const char **argv)
 {
 	SYS_SystemHandle syshandle;
 	bContext *C= CTX_create();
 	bArgs *ba;
 
+#ifdef WITH_PYTHON_MODULE
+#undef main
+#endif
+
 #ifdef WITH_BINRELOC
 	br_init( NULL );
 #endif
@@ -1192,10 +1203,13 @@
 	setuid(getuid()); /* end superuser */
 #endif
 
-
+#ifdef WITH_PYTHON_MODULE
+	G.background= 1; /* python module mode ALWAYS runs in background mode (for now) */
+#else
 	/* for all platforms, even windos has it! */
 	if(G.background) signal(SIGINT, blender_esc);	/* ctrl c out bg render */
-	
+#endif
+
 	/* background render uses this font too */
 	BKE_font_register_builtin(datatoc_Bfont, datatoc_Bfont_size);
 
@@ -1248,6 +1262,10 @@
 
 	BLI_argsFree(ba);
 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list