pythonnumpyc-api

C-API register a ufunc loop against builtin ufunc


I am looking to build a numpy extension module which declares a new structured dtype and provides the necessary inner ufunc loops to allow built-in math operations to be performed on it.

Following the guide on creating your own ufunc, I have been able to:

When exported as a module this works as intended, but requires the user to call the function via the package exported ufunc (i.e. my_package.add_uncertain); I would rather this implementation was available via numpy.add.

The language used in the registering a ufunc loop section of the numpy C-API docs seems to suggest that I should be able to register the ufunc loop against built-in ufuncs. To do so I believe I should pass the built-in PyUFuncGenericFunction to PyUFunc_RegisterLoopForDescr.

I would be very grateful to know if I am on the right track with this, and if so where I should look for the built-in PyUFuncGenericFunction


Solution

  • The solution, as contained within the numpy rational type test, was to import numpy with PyImport_Import then get the add ufunc using PyObject_GetAttrString, at which point the new inner loop could be registered:

      numpy_str = PyUnicode_FromString("numpy");
      if (!numpy_str) 
          return NULL;
      numpy = PyImport_Import(numpy_str);
      Py_DECREF(numpy_str);
      if (!numpy)
          return NULL;
    
      PyUFuncObject *add_ufunc = PyObject_GetAttrString(numpy, "add");
      if (!add_ufunc)
          return NULL;
    
      PyUFunc_RegisterLoopForDescr(
          add_ufunc,
          uncertain_double_dtype,
          &add_uncertain_double,
          add_uncertain_double_dtypes,
          NULL);