title: Building Cython module to run in C - ModuleNotFoundError
body: <p>I have a Cython module that I would like to call and run in C, but I am getting a ModuleNotFound error. I am following the instructions in the docs and other SO questions to the best of my knowledge, but there are limited examples of using Cython to convert Python to C beyond simple 1-file examples (i.e., non-modular).</p>
  <p>I am running Python 3.6 on Ubuntu (via Windows 10 WSL1).</p>
  <p>Here is a simplified example that shows the problem:</p>
  <p>tree:</p>
  <pre><code>├── Makefile
  ├── main.c
  ├── main_cy.pyx
  ├── mod_dir
  │   ├── __init__.pxd    #empty
  │   ├── mod.pxd
  │   └── mod.pyx
  └── setup_cy.py
  </code></pre>
  <p>mod_dir/mod.pxd:</p>
  <pre><code>cdef public int say_hello_from_mod() except -1
  </code></pre>
  <p>mod_dir/mod.pyx:</p>
  <pre><code>TEXT_TO_SAY = 'Hello from Python!'
  
  cdef public int say_hello_from_mod() except -1:
      print(TEXT_TO_SAY)
      return 0
  </code></pre>
  <p>main_cy.pyx:</p>
  <pre><code>print('hello from main_cy')
  from mod_dir.mod cimport say_hello_from_mod
  
  cdef public int say_hello_from_main_cy() except -1:
      say_hello_from_mod()
      return 0
  </code></pre>
  <p>main.c:</p>
  <pre><code>#include &quot;main_cy.h&quot;
  
  int main(int argc, char *argv[])
  {
      PyObject *pmodule;
      wchar_t *program;
  
      program = Py_DecodeLocale(argv[0], NULL);
      if (program == NULL) {
          fprintf(stderr, &quot;Fatal error: cannot decode argv[0], got %d arguments\n&quot;, argc);
          exit(1);
      }
  
      /* Add a built-in module, before Py_Initialize */
      if (PyImport_AppendInittab(&quot;main_cy&quot;, PyInit_main_cy) == -1) {
          fprintf(stderr, &quot;Error: could not extend in-built modules table\n&quot;);
          exit(1);
      }
  
      /* Pass argv[0] to the Python interpreter */
      Py_SetProgramName(program);
  
      /* Initialize the Python interpreter.  Required. If this step fails, it will be a fatal error. */
      Py_Initialize();
  
      /* Optionally import the module; alternatively, import can be deferred until the main_cy script imports it. */
      pmodule = PyImport_ImportModule(&quot;main_cy&quot;);
      if (!pmodule) {
          PyErr_Print();
          fprintf(stderr, &quot;Error: could not import module 'main_cy'\n&quot;);
          goto exit_with_error;
      }
  
      printf(&quot;Hello from C!\n&quot;);
  
      /* Now call into your module code. */
      if (say_hello_from_main_cy() &lt; 0) {
          PyErr_Print();
          fprintf(stderr, &quot;Error in Python code, exception was printed.\n&quot;);
          goto exit_with_error;
      }
  
      /* Clean up after using CPython. */
      PyMem_RawFree(program);
      Py_Finalize();
  
      return 0;
  
      /* Clean up in the error cases above. */
  exit_with_error:
      PyMem_RawFree(program);
      Py_Finalize();
      return 1;
  }
  </code></pre>
  <p>setup_cy.py:</p>
  <pre><code>from setuptools import setup
  from Cython.Build import cythonize
  
  setup(
      ext_modules = cythonize(['mod_dir/mod.pyx', 'main_cy.pyx'], annotate=False,language_level=3, include_path=['./', './mod_dir/'])
  )
  </code></pre>
  <p>Makefile:</p>
  <pre><code>all:
      gcc -c main_cy.c -o main_cy.o &lt;cflags&gt;
      gcc -c main.c -o main_c.o &lt;cflags&gt;
      gcc main_c.o main_cy.o -o main.o &lt;ldflags&gt; 
  </code></pre>
  <p>When I run the Cython setup (<code>python setup_cy.py build_ext --inplace</code>), it successfully creates the *.c, *.h, and *.so files in the main directory and in mod_dir. Then when I run make, it runs without errors and creates all of the *.o files. However, when I run the C executable (<code>./main.o</code>), I get the following runtime error:</p>
  <pre><code>Traceback (most recent call last):
    File &quot;main_cy.pyx&quot;, line 1, in init main_cy
      # main_cy.pyx
  ModuleNotFoundError: No module named 'mod_dir'
  Error: could not import module 'main_cy'
  </code></pre>
  <p>Thank you!</p>