In this chapter, we discuss Blender’s two largest “core” utility libraries. blenlib and blenkernel are the primary modules for generic processing and data. As such, they share a history in the Blender codebase. When appropriate, we will use Blender’s unit tests—written with Google Test1—to survey blenlib’s interface (BLI_* functions). Recall struct bContext is defined in blenkernel. We looked at the CTX_* API, a subset of the blenkernel API in Chapter 2. blenkernel’s API is generally accessed by BKE_* functions, which comprise a larger portion of its interface. blenkernel offloads data handling for makesdna, by operating on “DNA” data types. Other utility modules, namely, blenloader, blenfont, and blentranslation, are more specialized and beyond the scope of the current chapter.
Overview of blenlib
Internal misc libraries: math functions, lists, random, noise, memory pools, file operations (platform agnostic)
![../images/495914_1_En_4_Chapter/495914_1_En_4_Fig1_HTML.jpg](../images/495914_1_En_4_Chapter/495914_1_En_4_Fig1_HTML.jpg)
blenlib’s dependencies. It has limited dependency on other modules. There is some reliance on the repository’s internal support libraries, shown in the red
![../images/495914_1_En_4_Chapter/495914_1_En_4_Fig2_HTML.jpg](../images/495914_1_En_4_Chapter/495914_1_En_4_Fig2_HTML.jpg)
Partial dependency graph for both blenlib and blenkernel. Note that blenlib, blenlib, and makesdna each have a relatively high number of dependent modules
Google Test
One approach to exploring blenlib is to read the unit tests from source/blender/blenlib/tests/. Almost every source file in source/blender/blenlib/intern/ has a corresponding test file having .cc extension.
TEST() is provided by gtest. The format of Blender unit tests is shown
Running Tests
Partial listing for source/blender/blenlibblenlib/CMakeLists.txt. Note that the tests are compiled into a single executable blenlib_tests. This executable is written to the build directory in bin/tests/
It is not necessary to use ctest, in order to run unit tests. Unit tests are compiled to the build directory, in bin/tests/. All tests are compiled into blenlib_tests.
blenlib’s Unit Tests
Excerpt from tests/gtests/testing/testing.h. EXPECT_NEAR() is used for testing vector data
Partial unit test defined in source/blender/blenlib/tests/tests/BLI_array_test.cc. blenlib’s Array template class is tested
blenlib’s API
![../images/495914_1_En_4_Chapter/495914_1_En_4_Fig3_HTML.jpg](../images/495914_1_En_4_Chapter/495914_1_En_4_Fig3_HTML.jpg)
The blenlib (BLI_*) unit tests. Each file roughly corresponds to the interface files shown in Figure 4-4
![../images/495914_1_En_4_Chapter/495914_1_En_4_Fig4_HTML.jpg](../images/495914_1_En_4_Chapter/495914_1_En_4_Fig4_HTML.jpg)
blenlib’s interface headers. These files prototype BLI_* functions
While it is virtually impossible to list the entire BLI_* API here, a good way to access documentation separate from the source code is by using Doxygen-generated hyperlinked documents. Doxygen produces pdf or html from JavaDoc-style comments. However, most of the blenlib module’s API is not commented, and in many instances its API is either inlined (with a definition in the header only) or simply a preprocessor macro. Most source files in source/blender/blenlib/intern/ contain statically linked function definitions (e.g., bli_* functions or lower-level helper functions). These are called only indirectly by blenlib’s API. The repository provides a Doxygen configuration (doc/doxygen/Doxyfile), ready to run on the source. The configuration may be used at the command prompt via doxygen Doxyfile. Doxygen must first be installed.
Features of the blenlib API
- Data structures
Linked lists
Maps
Sets
kdtree
Bounding-volume hierarchy (bvh)
- Graph algorithms
A* search
Memory allocation
- Hashing
Open addressing
md5
mm2
mm3
Dynamic strings
Assertions
Byte swapping for big- and little-endian conversions
Command-line argument processing
File operations, such as renaming files
Path processing for files
Sorting
Thread management
Timers
- Two-dimensional processing
Geometry, that is, “rectangles”
Noise generation (texture generation)
Polygon fill
Voronoi
UV projection
Operating system–specific data types
Bitmaps
Console output
Random number generation
- Vector and quaternion math utility functions
Higher-order uses of basic functions for “easing” (animation)
Convex hull (geometry) processing
Color
Matrix operations
Statistics
Rotation
Interpolation
Quadrics
Voxels
blenlib implements byte operations (e.g., big- and little-endian conversion, etc.) used for blend files (see Chapter 2). As a reminder, blend files are essentially binary serializations of Blender “DNA.”
There are a few surprises. For instance, one is blenlib’s dynamic string type struct DynStr, defined in BLI_dynstr.c. (We have already seen that there is an internal library called string.) Another is that BLI_listbase.h has a dependency on DNA_listbase.h, where the functions used to insert and remove from Listbase are prototyped.
blenlib contains some redundancy. For linked-lists there are BLI_linklist.h and its associated BLI_link_utils.h, vs. BLI_listbase.h and BLI_listbase_wrapper.h. Both provide very similar utilities for Listbase. These are essentially two separate linked-list implementations.
blenlib API Examples
Now for some API examples. We use Doxygen-derived call graphs to see where calls are made to the API. We also look at API function definitions.
equals_m4m4() takes two-dimensional arrays of const floats. The function compares each column using equals_v4v4(). If all corresponding column vectors of two 4x4 matrices have identical entries, then matrices are considered equal. A boolean value is returned
The equals_v4v4() function . equals_v4v4() is inlined. This is specified by MINLINE, defined as static inline
![../images/495914_1_En_4_Chapter/495914_1_En_4_Fig5_HTML.jpg](../images/495914_1_En_4_Chapter/495914_1_En_4_Fig5_HTML.jpg)
Doxygen documentation for equals_m4m4()
![../images/495914_1_En_4_Chapter/495914_1_En_4_Fig6_HTML.jpg](../images/495914_1_En_4_Chapter/495914_1_En_4_Fig6_HTML.jpg)
BLI_Stack is an aggregate of StackChunk objects. The open diamond denotes this as an aggregation, not composition. We may have a BLI_Stack object without the need for any StackChunk objects composing the BLI_Stack, that is, the stack can be empty
The BLI_Stack and StackChunk structs from source/blender/blenlib/intern/stack.c. CHUNK_EMPTY, CHUNK_SIZE_DEFAULT, and CHUNK_ELEM_MIN definitions are shown. In the CHUNK_EMPTY macro, the negative one is cast to size_t (unsigned int). The size_t data type is returned from the sizeof()
Elided BLI_stack.h. Operation names are in boldface. ATTR_WARN_UNUSED_RESULT and ATTR_NONNULL() are defined in source/blender/blenlib/BLI_compiler_attrs.h. They specify attributes that can be verified at compile-time. For instance, with ATTR_NONNULL(), all arguments are checked by the compiler to be non-null. In the absence of any arguments to the macro, only pointers are checked to be non-null
BLI_stack_pop() , from source/blender/blenlib/intern/stack.c. The code uses BLI_assert() and stack_get_last_element() for retrieving the top element; that is, a “chunk” of bytes, of elem_size and type struct StackChunk
![../images/495914_1_En_4_Chapter/495914_1_En_4_Fig7_HTML.jpg](../images/495914_1_En_4_Chapter/495914_1_En_4_Fig7_HTML.jpg)
Documentation for BLI_stack_pop(). BLI_stack_pop() is referenced by other BLI_* functions and from the broader codebase
Overview of blenkernel
Kernel functions (data structure manipulation, allocation, free. No tools or UI stuff, very low level); kernel functions are shared with the blenderplayer, for loading data
![../images/495914_1_En_4_Chapter/495914_1_En_4_Fig8_HTML.jpg](../images/495914_1_En_4_Chapter/495914_1_En_4_Fig8_HTML.jpg)
Partial listing of the blenkernel module’s interface header files. These files prototype the BKE_* functions
Parts of the blenkernel module, such as those dealing with fluids (BKE_fluid.h, inter/fluid.c), character animation (BKE_anim.h, BKE_animsys.h, BKE_armature.h, intern/anim.c, intern/animsys.c, intern/armature.c), and other specialized areas, are peripheral to our exploration.
DNA Types and blenkernel
makesdna files and their blenkernel associated headers. Each BKE_*.h file contains API prototypes. These functions operate on corresponding data types defined in DNA_*.h.
makesdna File | blenkernel File |
---|---|
DNA_action_types.h | BKE_action.h |
DNA_anim_types.h DNA_boid_types.h DNA_brush_types.h DNA_cachefile_types.h DNA_camera_types.h DNA_cloth_types.h DNA_collection_types.h DNA_color_types.h | BKE_anim.h BKE_boids.h BKE_brush.h BKE_cachefile.h BKE_camera.h BKE_cloth.h BKE_collection.h BKE_colortools.h |
DNA_constraint_types.h DNA_curve_types.h DNA_curveprofile_types.h DNA_customdata_types.h DNA_dynamicpaint_types.h DNA_effect_types.h DNA_fluid_types.h DNA_freestyle_types.h DNA_gpencil_types.h DNA_image_types.h DNA_ipo_types.h DNA_key_types.h DNA_lattice_types.h DNA_layer_types.h DNA_light_types.h DNA_lightprobe_types.h DNA_linestyle_types.h DNA_mask_types.h DNA_material_types.h DNA_mesh_types.h DNA_modifier_types.h DNA_movieclip_types.h DNA_nla_types.h DNA_node_types.h DNA_object_types.h DNA_outliner_types.h | BKE_constraint.h BKE_curve.h BKE_curveprofile.h BKE_customdata.h BKE_dynamicpaint.h BKE_effect.h BKE_fluid.h BKE_freestyle.h BKE_gpencil.h BKE_image.h BKE_ipo.h BKE_key.h BKE_lattice.h BKE_layer.h BKE_light.h BKE_lightprobe.h BKE_linestyle.h BKE_mask.h BKE_material.h BKE_mesh.h BKE_modifier.h BKE_movieclip.h BKE_nla.h BKE_node.h BKE_object.h BKE_outliner_treehash.h |
DNA_packedFile_types.h DNA_particle_types.h DNA_rigidbody_types.h DNA_scene_types.h DNA_screen_types.h DNA_sequence_types.h DNA_shader_fx_types.h DNA_sound_types.h DNA_speaker_types.h DNA_text_types.h DNA_texture_types.h DNA_tracking_types.h DNA_world_types.h | BKE_packedFile.h BKE_particle.h BKE_rigidbody.h BKE_scene.h BKE_screen.h BKE_sequencer.h BKE_shader_fx.h BKE_sound.h BKE_speaker.h BKE_text.h BKE_texture.h BKE_tracking.h BKE_world.h |
blenkernel API Examples
BKE_world.h
The following examples are illustrative of blenkernel’s API for “DNA.”
Example BKE_world.h API prototypes. Function names are in boldface
BKE_camera.h
Example BKE_camera.h API prototypes. Function names are in boldface
As we have discussed, blenkernel provides functions for operating on various Blender objects. Importantly, not all of these objects originate in makesdna. Two prominent examples, struct Main and struct bContext, are in fact defined in blenkernel itself. Note that struct Main and struct bContext are only two examples. Other types fit this pattern as well, such as struct Global.
BKE_main.h
Example BKE_main.h API prototypes. Function names are in boldface
BKE_context.h
Example BKE_context.h API prototypes. Function names are in boldface
Summary
In this chapter, we looked at the blenlib and blenkernel modules. We also saw some of Blender’s unit tests, which are helpful in understanding parts of the codebase. Blender uses Google Test for at least some of its testing.
blendlib handles generic utilities in Blender, while blenkernel is more specific to the Blender application. Therefore, blenlib’s functionality, at least in principle, could be used by other similar programs. However, blenlib is tightly coupled to the Blender codebase—more so than, say GHOST, which is not part of the “core” codebase as we saw in Chapter 3.
blenkernel, on the other hand, offers a number of API functions for making needed manipulations on Blender “DNA,” and other state-keeping data structures. We provided a list of the correspondence between makesdna and blenkernel’s files, to illustrate the partial pairing of those modules.