text: from __future__ import division, print_function
  
  import os
  import genapi
  
  import numpy_api
  
  from genapi import \
          TypeApi, GlobalVarApi, FunctionApi, BoolValuesApi
  
  h_template = r"""
  #ifdef _UMATHMODULE
  
  extern NPY_NO_EXPORT PyTypeObject PyUFunc_Type;
  
  %s
  
  #else
  
  #if defined(PY_UFUNC_UNIQUE_SYMBOL)
  #define PyUFunc_API PY_UFUNC_UNIQUE_SYMBOL
  #endif
  
  #if defined(NO_IMPORT) || defined(NO_IMPORT_UFUNC)
  extern void **PyUFunc_API;
  #else
  #if defined(PY_UFUNC_UNIQUE_SYMBOL)
  void **PyUFunc_API;
  #else
  static void **PyUFunc_API=NULL;
  #endif
  #endif
  
  %s
  
  static NPY_INLINE int
  _import_umath(void)
  {
    PyObject *numpy = PyImport_ImportModule("numpy.core.umath");
    PyObject *c_api = NULL;
  
    if (numpy == NULL) {
        PyErr_SetString(PyExc_ImportError, "numpy.core.umath failed to import");
        return -1;
    }
    c_api = PyObject_GetAttrString(numpy, "_UFUNC_API");
    Py_DECREF(numpy);
    if (c_api == NULL) {
        PyErr_SetString(PyExc_AttributeError, "_UFUNC_API not found");
        return -1;
    }
  
  #if PY_VERSION_HEX >= 0x03000000
    if (!PyCapsule_CheckExact(c_api)) {
        PyErr_SetString(PyExc_RuntimeError, "_UFUNC_API is not PyCapsule object");
        Py_DECREF(c_api);
        return -1;
    }
    PyUFunc_API = (void **)PyCapsule_GetPointer(c_api, NULL);
  #else
    if (!PyCObject_Check(c_api)) {
        PyErr_SetString(PyExc_RuntimeError, "_UFUNC_API is not PyCObject object");
        Py_DECREF(c_api);
        return -1;
    }
    PyUFunc_API = (void **)PyCObject_AsVoidPtr(c_api);
  #endif
    Py_DECREF(c_api);
    if (PyUFunc_API == NULL) {
        PyErr_SetString(PyExc_RuntimeError, "_UFUNC_API is NULL pointer");
        return -1;
    }
    return 0;
  }
  
  #if PY_VERSION_HEX >= 0x03000000
  #define NUMPY_IMPORT_UMATH_RETVAL NULL
  #else
  #define NUMPY_IMPORT_UMATH_RETVAL
  #endif
  
  #define import_umath() \
      do {\
          UFUNC_NOFPE\
          if (_import_umath() < 0) {\
              PyErr_Print();\
              PyErr_SetString(PyExc_ImportError,\
                      "numpy.core.umath failed to import");\
              return NUMPY_IMPORT_UMATH_RETVAL;\
          }\
      } while(0)
  
  #define import_umath1(ret) \
      do {\
          UFUNC_NOFPE\
          if (_import_umath() < 0) {\
              PyErr_Print();\
              PyErr_SetString(PyExc_ImportError,\
                      "numpy.core.umath failed to import");\
              return ret;\
          }\
      } while(0)
  
  #define import_umath2(ret, msg) \
      do {\
          UFUNC_NOFPE\
          if (_import_umath() < 0) {\
              PyErr_Print();\
              PyErr_SetString(PyExc_ImportError, msg);\
              return ret;\
          }\
      } while(0)
  
  #define import_ufunc() \
      do {\
          UFUNC_NOFPE\
          if (_import_umath() < 0) {\
              PyErr_Print();\
              PyErr_SetString(PyExc_ImportError,\
                      "numpy.core.umath failed to import");\
          }\
      } while(0)
  
  #endif
  """
  
  c_template = r"""
  /* These pointers will be stored in the C-object for use in other
      extension modules
  */
  
  void *PyUFunc_API[] = {
  %s
  };
  """
  
  def generate_api(output_dir, force=False):
      basename = 'ufunc_api'
  
      h_file = os.path.join(output_dir, '__%s.h' % basename)
      c_file = os.path.join(output_dir, '__%s.c' % basename)
      d_file = os.path.join(output_dir, '%s.txt' % basename)
      targets = (h_file, c_file, d_file)
  
      sources = ['ufunc_api_order.txt']
  
      if (not force and not genapi.should_rebuild(targets, sources + [__file__])):
          return targets
      else:
          do_generate_api(targets, sources)
  
      return targets
  
  def do_generate_api(targets, sources):
      header_file = targets[0]
      c_file = targets[1]
      doc_file = targets[2]
  
      ufunc_api_index = genapi.merge_api_dicts((
              numpy_api.ufunc_funcs_api,
              numpy_api.ufunc_types_api))
      genapi.check_api_dict(ufunc_api_index)
  
      ufunc_api_list = genapi.get_api_functions('UFUNC_API', numpy_api.ufunc_funcs_api)
  
      # Create dict name -> *Api instance
      ufunc_api_dict = {}
      api_name = 'PyUFunc_API'
      for f in ufunc_api_list:
          name = f.name
          index = ufunc_api_index[name][0]
          annotations = ufunc_api_index[name][1:]
          ufunc_api_dict[name] = FunctionApi(f.name, index, annotations,
                                             f.return_type, f.args, api_name)
  
      for name, val in numpy_api.ufunc_types_api.items():
          index = val[0]
          ufunc_api_dict[name] = TypeApi(name, index, 'PyTypeObject', api_name)
  
      # set up object API
      module_list = []
      extension_list = []
      init_list = []
  
      for name, index in genapi.order_dict(ufunc_api_index):
          api_item = ufunc_api_dict[name]
          extension_list.append(api_item.define_from_array_api_string())
          init_list.append(api_item.array_api_define())
          module_list.append(api_item.internal_define())
  
      # Write to header
      s = h_template % ('\n'.join(module_list), '\n'.join(extension_list))
      genapi.write_file(header_file, s)
  
      # Write to c-code
      s = c_template % ',\n'.join(init_list)
      genapi.write_file(c_file, s)
  
      # Write to documentation
      s = '''
  =================
  NumPy Ufunc C-API
  =================
  '''
      for func in ufunc_api_list:
          s += func.to_ReST()
          s += '\n\n'
      genapi.write_file(doc_file, s)
  
      return targets
  