Accessing magic numbers / flags of the C header using Cython

Some standard C libraries that I want to handle with Cython have tons of flags. Cython docs indicate that I must replicate parts of the required header. Which is good when it comes to defining functions. They are usually replicated everywhere, including documents. But what about all these magic numbers?

If I want to call mmap , I can always find the function definition and paste it into the .pxd file:

 void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) 

But calling requires a ton of flags, such as PROT_READ , MAP_ANONYMOUS , etc. I have at least two problems with this:

First, itโ€™s an annoying job to track down exactly where these numbers are determined. In fact, I would rather write a .c file and print the desired values. Is there a better way to find the value of a given flag, for example PROT_READ ?

Secondly, how stable are these numbers? Having selected all the values โ€‹โ€‹I need and encoded them in my Cython source, what are the chances that the compilation on another platform has switched, say PROT_READ and PROT_EXEC ?

Even if the answer is that there are no good or right ways to do this, I would love to hear it. I can always admit that something is cumbersome if I know that I did not miss something.

+4
source share
3 answers

To use these constants from Cython, you do not need to determine exactly where they came from, or what they are more than with C. For example, your .pxd file may look like

 cdef extern from "foo.h": void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) cdef int PROT_READ cdef int MAP_ANONYMOUS ... 

As long as definitions (directly or indirectly) are included in foo.h, this should work fine.

+6
source

There are several possible alternatives:

  • Use flags in Python mmap module.
    • simply
    • only works with existing Python bindings
  • First use a Python mmap object and pass it to your Cython code
    • simpler discovery
    • may have some python overhead
  • Use the ctypeslib code ctypeslib
    • some docs on how to extract constants
    • gccxml required
  • Just copy the numbers.

Moreover, the numbers are very, very stable. If they changed, each and every C program using mmap would have to be recompiled, since the flags from the headers are in binary format.

EDIT : mmap is part of POSIX , but a quick read did not reveal, the flags should be the same for all platforms.

+2
source

Write the file foo.c with this as content:

 #include <sys/mman.h> 

Then run

 cpp -dM foo.c | grep -v __ | awk '{if ($3) print $2, "=", $3}' > mman.py 

which will create a python file that will determine all the constants from mman.h

Obviously, you can do this for a few inclusions if you want.

The resulting file may need a little cleanup, but it will force you to close.

+1
source

Source: https://habr.com/ru/post/1300401/


All Articles