inlinecpp module

This module lets you write functions in C++ that are accessible from Python. When necessary, your C++ code is automatically compiled into a library and the library is loaded, but the code won’t be compiled when the library already exists, and the library won’t be reloaded when it’s already loaded.

NOTE: The Python ctypes module does not support 64-bit Windows in Python 2.5,
so this module requires Python 2.6 on 64-bit Windows.
Consider this example:
mymodule = inlinecpp.createLibrary(
name=”example_string_library”, includes=”#include <UT/UT_String.h>”, function_sources=[

“”” int matchesPattern(const char *str, const char *pattern) {

return UT_String(str).multiMatch(pattern);

} “”“])

string = “one” for pattern in “o*”, “x*”, “^o*”:

print “%s matches %s: %s” % (repr(string), repr(pattern),
bool(mymodule.matchesPattern(string, pattern)))

The call to inlinecpp.createLibrary receives your C++ source code and returns a module-like object (assigned to the variable mymodule). You can then call mymodule.matchesPattern to invoke the corresponding C++ function. If you forget which parameters to pass to matchesPattern, you can get the C++ signature with:

>>> mymodule.matchesPattern.signature()
'int matchesPattern(const char * str, const char * pattern)'

Note that subsequent calls to createLibrary with the exact same parameters will not recompile your module, and will not reload it if it’s been loaded in the current session.

This module uses the hcustom HDK tool to compile your C++ code. If your code contains a compiler error, it raises a CompilerError exception. You can compile your code with debugging enabled by passing debug=True to createLibrary.

If you want to check for compiler warnings, call the _compiler_output method of the module-like object. Note that if the library was already compiled when it was loaded, calling _compiler_output will force it to be recompiled.

>>> print mymodule._compiler_output()
Making /home/user/houdiniX.Y/inlinecpp/example_string_library_Linux_x86_64_j5c9Dz
T525OU0VdJ5uL0kw.o and /home/user/houdiniX.Y/inlinecpp/example_string_library_Lin
ux_x86_64_j5c9DzT525OU0VdJ5uL0kw.so from /home/user/houdiniX.Y/inlinecpp/example_
string_library_Linux_x86_64_j5c9DzT525OU0VdJ5uL0kw.C
Your C++ functions may have the following parameter types:
int float (pass a Python float) double (pass a Python float) const char * (pass a Python str object) bool (Python 2.6 and up only) GU_Detail * (pass a hou.Geometry object from inside a Python sop) const GU_Detail * (pass a hou.Geometry object) OP_Node * (pass a hou.Node object) CHOP_Node * (pass a hou.ChopNode) COP2_Node * (pass a hou.CopNode) DOP_Node * (pass a hou.DopNode) OBJ_Node * (pass a hou.ObjNode) POP_Node * (pass a hou.PopNode) POPNET_Node * (pass a hou.PopNetNode) ROP_Node * (pass a hou.RopNode) SHOP_Node * (pass a hou.ShopNode) SOP_Node * (pass a hou.SopNode) VOP_Node * (pass a hou.VopNode) VOPNET_Node * (pass a hou.VopNetNode) OP_Operator * (pass a hou.NodeType) PRM_Tuple * (pass a hou.ParmTuple) CL_Track * (pass a hou.Track) const SIM_Data * (pass a hou.DopData) UT_Vector2D * (pass a hou.Vector2) UT_Vector3D * (pass a hou.Vector3) UT_Vector4D * (pass a hou.Vector4) UT_DMatrix3 * (pass a hou.Matrix3) UT_DMatrix4 * (pass a hou.Matrix4) UT_BoundingBox * (pass a hou.BoundingBox) UT_Color * (pass a hou.Color) UT_QuaternionD * (pass a hou.Quaternion)
Your C++ functions may have one of the following return values:
void int float double const char * (a null-terminated string that will not be freed) char * (a null-terminated string that will be freed with free()) bool (Python 2.6 and up only)

The shared library file (.so on Linux, .dll on Windows, and .dylib on Mac) is put in your $HOME/houdiniX.Y/inlinecpp directory. It is named

<name>_<platform>_<processor>_<houdini_version>_<checksum>.{so|dll|dylib}

where the name is the name you pass to createLibrary and the checksum is based on the C++ source code. When you change the source code, the shared library name will be different, and this module recompiles the new library and automatically deletes any old libraries. As long as the C++ source code doesn’t change (for example, if it’s embedded inside a digital asset), you can be sure the checksum won’t change and you can distribute the library within your facility as you would with any other HDK library.

For more information and examples, see the “Extending with C++” subsection of the “Houdini Object Module” section of Houdini’s documentation.

class inlinecpp.ConstGU_DetailHandle(geometry)

Bases: hutil.cppinline.ConverterHandle

as_pointer()
destroy()
class inlinecpp.GU_DetailHandle(geometry)

Bases: inlinecpp.ConstGU_DetailHandle

class inlinecpp.HcustomCompilerHook

Bases: hutil.cppinline.CompilerHook

clean_up_after_compiling(cpp_file_path, output_shared_library_path, debug, include_dirs, link_dirs, link_libs)

Remove any temporary files that were created during the compilation process.

default_shared_library_directory()

Return a full path to the directory where shared libraries will be placed when initially compiled.

find_shared_library(shared_library_file_name)

Search for a shared library with the given name, returning its full path or None if it couldn’t be found. This method lets you search for the library in more than the default directory.

get_compile_command(cpp_file_path, output_shared_library_path, debug, include_dirs, link_dirs, link_libs)

Return a string containing the command to compile, and optionally also link, the given C++ file.

inlinecpp.createLibrary(name, includes='', function_sources=(), debug=False, catch_crashes=None, acquire_hom_lock=False, structs=(), include_dirs=(), link_dirs=(), link_libs=(), config=None)

Create a library of C++ functions from C++ source, returning it if it’s already loaded, compiling it only if it hasn’t already been compiled.

name:
A unique name used to build the shared object file’s name.
includes:
A string containing #include lines to go before your functions. You can also put helper functions in this string that can be called from your functions but are not exposed to Python.
function_sources:
A sequence of strings, with each string containing the source code to one of your functions. The string must begin with the signature for your function so it can be parsed out.
debug:
If True, the code will be compiled with debug information. If True and you do not specify a value for catch_crashes, Houdini will also attempt to convert crashes in your C++ code into Python RuntimeError exceptions.
catch_crashes:
If True, Houdini will attempt to catch crashes in your C++ code and convert them into Python RuntimeError exceptions containing a C++ stack trace. There is no guarantee that Houdini can always recover from crashes in your C++ code, so Houdini may still crash even if this parameter is set to True. Setting this parameter to None (the default) will make it use the same setting as the debug parameter.
structs:

A sequence of descriptions of C structures that can be used as return values. Each structure description is a pair, where the first element is the name of the structure and the second is a sequence of member descriptions. Each member description is a pair of strings containing the member name and type.

Member types may be one of: - A format characters used by Python’s struct module (e.g. “i” for

integer, “d” for double, “c” for character, etc.).
  • A format character preceded by a “*”, to indicate an array of those elements. For example, “*i” is an array of integers.
  • The name of an earlier type in the sequence of structs.

Note that, instead of a sequence of member descriptions, the second element of a struct description may be a string. In this case, the type will be a typedef. These typedefs are useful to create type names for arrays of values.

For example, the following sequence creates a Point struct with two integer members x and y, and a Data struct containing members named “tolerance” (a double), “single_point” (a Point), and “points” (an array of Points. One of your C++ functions could return a “Data” value that is automatically converted into Python objects.

(
(“Point”, (
(“x”, “i”), (“y”, “i”),

)), (“Data”, (

(“tolerance”, “d”), (“single_point”, “Point”), (“points”, “*Point”),

)),

)

The following sequence creates an IntArray struct:
((“IntArray”, “*i”),)

One of your C++ functions could then use IntArray as the return type and return a std::vector<int>.

include_dirs:
A sequence of extra directory paths to be used to search for include files. These paths are passed as -I options to the hcustom command when compiling the C++ code.
link_dirs:
A sequence of extra directory paths to be used to search for shared or static libraries that the C++ code links against. These paths are passed as -L options to the hcustom command.
link_libs:
A sequence of names of extra libraries that the C++ code needs to link against. These library names are passed as -l options to the hcustom command.
config:
Either a cppinline.Config object to customize how cppinline works, or None.
acquire_hom_lock:
If True, the code will be automatically modified to use a HOM_AutoLock, to ensure threadsafe access to the C++ object when the Python code is being run in a separate thread. If your code modifies Houdini’s internal state, set this parameter to True.
inlinecpp.extendClass(cls, library_name, includes='', function_sources=(), debug=False, catch_crashes=None, structs=(), auto_add_include=True, include_dirs=(), link_dirs=(), link_libs=(), config=None)

Extend a hou class by adding methods implemented in C++.

cls is the hou module class you’re extending. The rest of the arguments are the same as for createLibrary, except acquire_hom_lock is always True. Note that this function automatically adds a #include line for the underlying C++ class unless auto_add_include is False.

The first parameter to your C++ functions must be a pointer to a C++ object corresponding to the hou object. See the module documentation for the mapping from hou classes to C++ HDK classes.

Note that if you are passing hou.Geometry objects, you must provide a const GU_Detail * if it can be called on a read-only hou.Geometry object and a GU_Detail * only if it can only be called on a hou.Geometry object from within a Python SOP.