# tag: cpp

PYTHON setup.py build_ext --inplace
PYTHON test.py

######## setup.py ########

from Cython.Build.Dependencies import cythonize

from distutils.core import setup

exts = cythonize("*.pyx")
for e in exts:
    if e.name == "d":
        e.sources.append("a.c")

setup(
  ext_modules = exts,
)

######## a.pxd ########

ctypedef api float flt

cdef int   int0
cdef float flt0

cdef api int   int1
cdef api float flt1

cdef public api int int2
cdef public api flt flt2

cdef class A0:
     pass

ctypedef api class A1 [
     type A1_Type, 
     object A1Object
     ]:
     pass

ctypedef public api class A2 [
     type A2_Type, 
     object A2Object
     ]:
     pass

cdef A0 a0
cdef api A1 a1
cdef public api A2 a2

######## a.pyx ########

cdef int   int0 = 1, int1 = 1, int2 = 1
cdef float flt0 = 1, flt1 = 1, flt2 = 1

cdef api int int3 = 1
cdef api flt flt3 = 1

cdef public int int4 = 1
cdef public flt flt4 = 1

def get_int():
    return (int0, int1, int2, int3, int4)

def get_flt():
    return (flt0, flt1, flt2, flt3, flt4)

cdef class A0: pass
cdef class A1: pass
cdef class A2: pass

cdef A0 a0 = A0()
cdef api A1 a1 = A1()
cdef public api A2 a2 = A2()

######## b.pyx ########

from a cimport *

int0 = int1 = int2 = 7
flt0 = flt1 = flt2 = 7

######## c.pyx ########

# distutils: language = c++

cdef extern from "a_api.h":
     int import_a() except -1
     ctypedef float flt
     int int1, int2, int3
     flt flt1, flt2, flt3

import_a()

int1 = int2 = int3 = 5
flt1 = flt2 = flt3 = 5

######## inita.h ########

#if PY_MAJOR_VERSION >= 3
void inita(void)
{
   PyObject *sys_modules = NULL;
   PyObject *mod = NULL;
   sys_modules = PyImport_GetModuleDict();
   if (!sys_modules) return;
   mod = PyInit_a();
   if (!mod) return;
   PyDict_SetItemString(sys_modules, (char*)"a", mod);
}
#endif

######## d.pyx ########

cdef extern from "a.h":
     pass
cdef extern from "inita.h":
     pass
cdef extern from "a.h":
     void inita() except *
     ctypedef float flt
     int int2, int4
     flt flt2, flt4

inita()

int2 = int4 = 3
flt2 = flt4 = 3

######## test.py ########

import a
assert a.get_int() == (1,1,1,1,1)
assert a.get_flt() == (1,1,1,1,1)

import b
assert a.get_int() == (7,7,7,1,1)
assert a.get_flt() == (7,7,7,1,1)

import c
assert a.get_int() == (7,5,5,5,1)
assert a.get_flt() == (7,5,5,5,1)

import d
import a
assert a.get_int() == (1,1,3,1,3)
assert a.get_flt() == (1,1,3,1,3)
