Expose a C++ global variable in Python
Question: I'm trying to access to a C++ global variable in my Python code, using Cython.

Let's say I have the following array in my C++ code:

    
    
    // Project.cpp
    int myArr[2] = { 0, 1 };
    

So, in Cython to define a pointer to _myArr_ :

    
    
    cdef extern int * myArr_ptr
    

Does **myArr_ptr** really points to the C++ array? Or is just a random value?


Answer: OK, the problem is:

`Project.cpp` has a global `int *myArr;`, it's not listed in `Project.h`, and
you want to access it from Cython without importing `Project.cpp`.

In the comments, you say:

> I can't include Project.cpp because this file will try to include other
> files that were already included and will try to redefine many variables.

The way you described it, there might be an elementary error here. You
probably know these basic things, so please don't be insulted that I bring
them up, but I just want to be thorough:

First, if your header files don't have guards against multiple inclusion, fix
that, and then you don't need to worry about "I can't include `Project.cpp`
because this file will try to include other files that were already included
and will try to redefine many variables." (And if you don't have header files,
and you're just doing everything in .cpp files with explicit `extern`
statements all over the place, don't do that—it's a bad idea in C and C++,
well before you get to Cythonizing.)

Second, if your module is meant to interface to a .so/.dll/.dylib that
`Project.cpp` is part of, you shouldn't be building against the source to that
library, but to the installed interface. On the other hand, if your module is
meant to directly include the C++ code, then you _have_ to include
`Project.cpp`. If you use `extern` declarations to reference things that you
aren't going to link in, you're just going to get a linker error—or, if you're
unlucky, everything will build but then fail at runtime.

Third, if it isn't actually global, you can't access from outside of
`Project.cpp`—for reasons of scope, lifetime, or linkage, no other kind of
variable is usable in a separate implementation file.

Again, I assume you know all those basic things, and I just misread your
comment. There _is_ a real problem case where you need to wrap something with
a poorly-designed API that requires you to reach into the internals, and that
can be tricky sometimes, and you probably did run into such a thing, and I
just haven't figured out exactly how.

There are three basic solutions.

First, obviously, if you can build a proper native API, then wrapping that API
in Cython is trivial. And this is useful for other reasons, at the same time.
Sometimes, this would be too much time and effort—e.g., if the native library
wasn't designed to be driven externally, and is a mass of 10 years of legacy
maintenance, and the only reason you're ever going to have to wrap it is the
current Cython project, you may not want to clean it up. Or, if it's a
rapidly-changing library that you need to keep up to date with and don't have
source control over, forking it and trying to keep in sync can be a nightmare.
And so on. But if there's no such reason in your case, this is the right
answer. If you can just `cdef extern from "project.h"`, everything is easy.

You can do a simpler version of that by creating a "shim API" at the native
level, creating separate `.h` files with the appropriate extern, function, and
type declarations for the various, functions, and types you need to use from
the internals. Then, you can just `cdef extern from "project_extras.h"`.

Finally, you can always write explicit `cdef extern` statements for anything,
without telling Cython where any of it comes from. Cython will turn this into
the appropriate native externs in the generated code, and if you get
everything right, it will work. There are some downsides here—[the
docs](http://docs.cython.org/src/userguide/external_C_code.html#referencing-c-
header-files) explain all the advantages of `cdef extern from` that you'll be
giving up. The short version is, your Cython declarations have to exactly
match the native declarations; otherwise, instead of getting automatically
fixed up or raising a nice error at the Cython stage, you'll get an
inscrutable error message from the C compiler referring to the unreadable
Cython-generated C code instead of your actual code—or, worse, code that
compiles but does the wrong thing.

For the case of a simple `int *` or `int []` value, all of this scarcely
matters, because that doesn't need any interpretation; a plain `cdef extern`
should be just fine.

