How do I override an operator that was written in C?

I’m looking for a way to override the operator bpy.types.OBJECT_OT_shape_key_move as well as a few others. I’ve basically finished writing labels into shape keys, but I need other scripts/users to call my functions instead of the originals, so the state of my labels don’t become invalid. I still need to be able to call the original function bpy.ops.object.shape_key_move in the operator I replace it with, but other scripts in blender should only see mine. Basically something like this, but with an operator that was originally written in C. At least, I think these were written in C.

sorry for bumping, but in case anyone finds this thread, here’s an easy solution:

wrap the “original” operator inside a custom python operator, e.g.:

import bpy

class SimpleOperator(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.simple_operator"
    bl_label = "Simple Object Operator"


    @classmethod
    def poll(cls, context):
        return context.active_object is not None


    def execute(self, context):
        # Call any operator (C/python) here...
        bpy.ops.transform.translate(value=(0,0,1))
        return {'FINISHED'}




def register():
    bpy.utils.register_class(SimpleOperator)




def unregister():
    bpy.utils.unregister_class(SimpleOperator)




if __name__ == "__main__":
    register()


    # test call
    bpy.ops.object.simple_operator()

The example you’ve given is indeed the standard method of creating an operator. I certainly hope it’s useful to anyone who finds this thread. However, the original question was asking how to override/monkey patch a C operator, in order to extend the original functionality. The essential idea was that ALL parts of blender, including scripts written by other authors would continue to call the original operator (bpy.ops.object.shape_key_move in my example) but that operator would be extended to support further functionality (labels in my example).

i admit it’s the most simple “wrapping” of a c-operator. However, it shows what is possible: you can perform tasks before, then call c-op (may pass parameters), perform tasks afterwards. There is nothing more you can do, and probably won’t be able in future as well. How could python hook up to the middle of the compiled c-code? Unless you inject into the exe, i don’t see a way here.

This is the most i could money-hijack (?) the border select for my task:

import bpy, bmesh

bl_info = {
    "name": "Border Select Intersection",
    "author": "CoDEmanX",
    "version": (1, 1),
    "blender": (2, 66, 0),
    "location": "View3D > Spacebar > Border Select Intersect",
    "description": "Make a selection, then run this operator to border select the desired selection intersection",
    "warning": "",
    "wiki_url": "",
    "tracker_url": "",
    "category": "3D View"}


def store_sel():
    bm = MESH_OT_select_border_intersect.bm
    
    if 'select_old' in bm.loops.layers.int.keys():
        sel = bm.loops.layers.int['select_old']
    else:
        sel = bm.loops.layers.int.new("select_old")
        
    for v in bm.verts:
        if not v.link_loops: # IndexError?!
            continue
        v.link_loops[0][sel] = v.select
            
def restore_sel(me):
    bm = MESH_OT_select_border_intersect.bm
    
    sel = bm.loops.layers.int['select_old']
        
    for v in bm.verts:
        if not v.link_loops:
            continue
        if not (v.select and v.link_loops[0][sel]):
            v.select_set(False)


    #bm.select_mode = {'VERT'}
    #bm.select_flush_mode()
    bm.select_flush(False)
    me.update()


def changed_sel():
    bm = MESH_OT_select_border_intersect.bm
    
    sel = bm.loops.layers.int['select_old']
        
    for v in bm.verts:
        if not v.link_loops:
            continue
        if v.select != v.link_loops[0][sel]:
            return True
    return False




class MESH_OT_select_border_intersect(bpy.types.Operator):
    """Border select an existing selection and make only the intersection selected"""
    bl_idname = "mesh.select_border_intersect"
    bl_label = "Border Select Intersect"
    bl_options = {'REGISTER'}
    
    init = True
    bm = None


    def modal(self, context, event):
        
        if changed_sel():
            restore_sel(context.object.data)
            return {'FINISHED'}


        elif event.type in {'RIGHTMOUSE', 'ESC'}:
            return {'CANCELLED'}


        if self.init:        
            bpy.ops.view3d.select_border('INVOKE_DEFAULT', extend=False)
            self.init = False


        return {'RUNNING_MODAL'}
        #return {'PASS_THROUGH'} # Makes no difference


    def invoke(self, context, event):
        if (context.object and 
            context.object.type == 'MESH' and
            context.object.mode == 'EDIT'):
                
            MESH_OT_select_border_intersect.bm = bmesh.from_edit_mesh(context.object.data)
            store_sel()
            context.window_manager.modal_handler_add(self)
            return {'RUNNING_MODAL'}
        else:
            self.report({'WARNING'}, "No active editmesh, could not finish")
            return {'CANCELLED'}


def register():
    bpy.utils.register_class(MESH_OT_select_border_intersect)




def unregister():
    bpy.utils.unregister_class(MESH_OT_select_border_intersect)




if __name__ == "__main__":
    register()