text: from __future__ import division, print_function
  
  import os
  import genapi
  
  from genapi import \
          TypeApi, GlobalVarApi, FunctionApi, BoolValuesApi
  
  import numpy_api
  
  h_template = r"""
  #ifdef _MULTIARRAYMODULE
  
  typedef struct {
          PyObject_HEAD
          npy_bool obval;
  } PyBoolScalarObject;
  
  #ifdef NPY_ENABLE_SEPARATE_COMPILATION
  extern NPY_NO_EXPORT PyTypeObject PyArrayMapIter_Type;
  extern NPY_NO_EXPORT PyTypeObject PyArrayNeighborhoodIter_Type;
  extern NPY_NO_EXPORT PyBoolScalarObject _PyArrayScalar_BoolValues[2];
  #else
  NPY_NO_EXPORT PyTypeObject PyArrayMapIter_Type;
  NPY_NO_EXPORT PyTypeObject PyArrayNeighborhoodIter_Type;
  NPY_NO_EXPORT PyBoolScalarObject _PyArrayScalar_BoolValues[2];
  #endif
  
  %s
  
  #else
  
  #if defined(PY_ARRAY_UNIQUE_SYMBOL)
  #define PyArray_API PY_ARRAY_UNIQUE_SYMBOL
  #endif
  
  #if defined(NO_IMPORT) || defined(NO_IMPORT_ARRAY)
  extern void **PyArray_API;
  #else
  #if defined(PY_ARRAY_UNIQUE_SYMBOL)
  void **PyArray_API;
  #else
  static void **PyArray_API=NULL;
  #endif
  #endif
  
  %s
  
  #if !defined(NO_IMPORT_ARRAY) && !defined(NO_IMPORT)
  static int
  _import_array(void)
  {
    int st;
    PyObject *numpy = PyImport_ImportModule("numpy.core.multiarray");
    PyObject *c_api = NULL;
  
    if (numpy == NULL) {
        PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import");
        return -1;
    }
    c_api = PyObject_GetAttrString(numpy, "_ARRAY_API");
    Py_DECREF(numpy);
    if (c_api == NULL) {
        PyErr_SetString(PyExc_AttributeError, "_ARRAY_API not found");
        return -1;
    }
  
  #if PY_VERSION_HEX >= 0x03000000
    if (!PyCapsule_CheckExact(c_api)) {
        PyErr_SetString(PyExc_RuntimeError, "_ARRAY_API is not PyCapsule object");
        Py_DECREF(c_api);
        return -1;
    }
    PyArray_API = (void **)PyCapsule_GetPointer(c_api, NULL);
  #else
    if (!PyCObject_Check(c_api)) {
        PyErr_SetString(PyExc_RuntimeError, "_ARRAY_API is not PyCObject object");
        Py_DECREF(c_api);
        return -1;
    }
    PyArray_API = (void **)PyCObject_AsVoidPtr(c_api);
  #endif
    Py_DECREF(c_api);
    if (PyArray_API == NULL) {
        PyErr_SetString(PyExc_RuntimeError, "_ARRAY_API is NULL pointer");
        return -1;
    }
  
    /* Perform runtime check of C API version */
    if (NPY_VERSION != PyArray_GetNDArrayCVersion()) {
        PyErr_Format(PyExc_RuntimeError, "module compiled against "\
               "ABI version %%x but this version of numpy is %%x", \
               (int) NPY_VERSION, (int) PyArray_GetNDArrayCVersion());
        return -1;
    }
    if (NPY_FEATURE_VERSION > PyArray_GetNDArrayCFeatureVersion()) {
        PyErr_Format(PyExc_RuntimeError, "module compiled against "\
               "API version %%x but this version of numpy is %%x", \
               (int) NPY_FEATURE_VERSION, (int) PyArray_GetNDArrayCFeatureVersion());
        return -1;
    }
  
    /*
     * Perform runtime check of endianness and check it matches the one set by
     * the headers (npy_endian.h) as a safeguard
     */
    st = PyArray_GetEndianness();
    if (st == NPY_CPU_UNKNOWN_ENDIAN) {
        PyErr_Format(PyExc_RuntimeError, "FATAL: module compiled as unknown endian");
        return -1;
    }
  #if NPY_BYTE_ORDER == NPY_BIG_ENDIAN
    if (st != NPY_CPU_BIG) {
        PyErr_Format(PyExc_RuntimeError, "FATAL: module compiled as "\
               "big endian, but detected different endianness at runtime");
        return -1;
    }
  #elif NPY_BYTE_ORDER == NPY_LITTLE_ENDIAN
    if (st != NPY_CPU_LITTLE) {
        PyErr_Format(PyExc_RuntimeError, "FATAL: module compiled as "\
               "little endian, but detected different endianness at runtime");
        return -1;
    }
  #endif
  
    return 0;
  }
  
  #if PY_VERSION_HEX >= 0x03000000
  #define NUMPY_IMPORT_ARRAY_RETVAL NULL
  #else
  #define NUMPY_IMPORT_ARRAY_RETVAL
  #endif
  
  #define import_array() {if (_import_array() < 0) {PyErr_Print(); PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import"); return NUMPY_IMPORT_ARRAY_RETVAL; } }
  
  #define import_array1(ret) {if (_import_array() < 0) {PyErr_Print(); PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import"); return ret; } }
  
  #define import_array2(msg, ret) {if (_import_array() < 0) {PyErr_Print(); PyErr_SetString(PyExc_ImportError, msg); return ret; } }
  
  #endif
  
  #endif
  """
  
  
  c_template = r"""
  /* These pointers will be stored in the C-object for use in other
      extension modules
  */
  
  void *PyArray_API[] = {
  %s
  };
  """
  
  c_api_header = """
  ===========
  Numpy C-API
  ===========
  """
  
  def generate_api(output_dir, force=False):
      basename = 'multiarray_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 = numpy_api.multiarray_api
  
      if (not force and not genapi.should_rebuild(targets, [numpy_api.__file__, __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]
  
      global_vars = sources[0]
      global_vars_types = sources[1]
      scalar_bool_values = sources[2]
      types_api = sources[3]
      multiarray_funcs = sources[4]
  
      # Remove global_vars_type: not a api dict
      multiarray_api = sources[:1] + sources[2:]
  
      module_list = []
      extension_list = []
      init_list = []
  
      # Check multiarray api indexes
      multiarray_api_index = genapi.merge_api_dicts(multiarray_api)
      genapi.check_api_dict(multiarray_api_index)
  
      numpyapi_list = genapi.get_api_functions('NUMPY_API',
                                                multiarray_funcs)
      ordered_funcs_api = genapi.order_dict(multiarray_funcs)
  
      # Create dict name -> *Api instance
      api_name = 'PyArray_API'
      multiarray_api_dict = {}
      for f in numpyapi_list:
          name = f.name
          index = multiarray_funcs[name]
          multiarray_api_dict[f.name] = FunctionApi(f.name, index, f.return_type,
                                                    f.args, api_name)
  
      for name, index in global_vars.items():
          type = global_vars_types[name]
          multiarray_api_dict[name] = GlobalVarApi(name, index, type, api_name)
  
      for name, index in scalar_bool_values.items():
          multiarray_api_dict[name] = BoolValuesApi(name, index, api_name)
  
      for name, index in types_api.items():
          multiarray_api_dict[name] = TypeApi(name, index, 'PyTypeObject', api_name)
  
      if len(multiarray_api_dict) != len(multiarray_api_index):
          raise AssertionError("Multiarray API size mismatch %d %d" %
                          (len(multiarray_api_dict), len(multiarray_api_index)))
  
      extension_list = []
      for name, index in genapi.order_dict(multiarray_api_index):
          api_item = multiarray_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
      fid = open(header_file, 'w')
      s = h_template % ('\n'.join(module_list), '\n'.join(extension_list))
      fid.write(s)
      fid.close()
  
      # Write to c-code
      fid = open(c_file, 'w')
      s = c_template % ',\n'.join(init_list)
      fid.write(s)
      fid.close()
  
      # write to documentation
      fid = open(doc_file, 'w')
      fid.write(c_api_header)
      for func in numpyapi_list:
          fid.write(func.to_ReST())
          fid.write('\n\n')
      fid.close()
  
      return targets
  