There are two types of local variables you can add to a SOP. The first type are entirely custom local variables. These are often useful for generators. To implement these you need to override the SOP_Node::getVariableValue and when instantiating your SOP with OP_Operator constructor (inside newSopOperator) include your static CH_LocalVariable list. An example of this approach is in SOP_Star.C and SOP_Star.h.
The second type of local variable is one operates per point, vertex, or primitive, and binds the standard attributes to local variables. This creates the $PT, $PRIM, $NPT, $CR, etc, variables that artists expect with SOPs that iterate over points or primitives. This also includes the bindings specified by the varmap attribute created by the Attrib Create SOP.
To bind the standard local variables you first inform Houdini of what precedence the variables should have. If you have both primitive and point Cd attributes, Houdini needs to know which one gets bound to $CR. This is done with the SOP_Node::setVariableOrder.
Next the geometry to use for the binding is passed to SOP_Node::setCurGdh. This can bind two different geometries using the input parameter. Input 0 would be bound to $CR and input 1 to $CR2. Which GU_DetailHandle to use affects the behaviour. You can either use SOP_Node::myGdpHandle to use the same GU_Detail as your SOP's gdp pointer, or you can use one of your input's geometry fetched by SOP_Node::inputGeoHandle.
After your precedence is set and GU_Detail specified you need to actually bind the local variables. Until this point a reference to $CR would fail in an expression. This is done by calling SOP_Node::setupLocalVars.
During your cook you may now evaluate parameters (with OP_Node::evalInt or similar) and have the appropriate localvariables present. However, you still need to specify what the currently processed point, vertex, and/or primitive is. This is done by writing to SOP_Node::myCurPt, SOP_Node::myCurVtx, and SOP_Node::myCurPrim. The point, primitive, or vertex set must belong to the same GU_Detail that you bound with the SOP_Node::setCurGdh.
It is important you do not leave dangling GEO_Point pointers in the local variable code or it might be picked up in UI evaluation when the GU_Detail no longer exists. To guard against this, after completing your cook you should invoke SOP_Node::resetLocalVarRefs.