开发者

python extension module initialisation - multiple files

开发者 https://www.devze.com 2023-02-11 09:47 出处:网络
Having created a C library consisting of many source and header files, I now need to wrap it with a Python layer, so I can \"import\" it.

Having created a C library consisting of many source and header files, I now need to wrap it with a Python layer, so I can "import" it.

I have implemented the static method to be called from Python, and I need to specify which methods the module should expose to the interpreter.

However, the documentation only seems to deal with the very simple case of having a single source file when it comes to specifying what can be called, since the only nonstatic method has to be the init, which registers the methods.

As far as I can tell it is impossible to call methods in other source files if they are declared static in C (please correct me if I'm wrong there) so, it is only possible to have one C file per python module, since you're only allowed one non-static method in the whole thing.

Is this really the case? Must you structure your code badly/not at all if you want to access it from Python?

EDIT:

So, the way I got this working in the end was to use Cython. Not only did it take about an hour to rewrite the c/python interface (which 开发者_Go百科had previously taken about a day due to all the reference counting rules etc) but it also handles all the build issues for you, and has clear documentation describing exactly which methods will be available from python.

In particular, the documentation chapters I used were the build instructions, how to call C libraries, the language basics and how to cast types, particularly pointers.

For anyone looking to wrap existing complex-structured C code (i.e. anything more than a single file) as a python library, I can highly recommend Cython.


It's not actually a requirement for module initialization function to be the only non-static symbol in a module. It's more of a best practice that prevents polluting the flat namespace C uses for runtime symbols. The other common approach for this is placing a library-specific prefix on all exported symbols. You can do either though the static-only approach is generally considered to be cleaner and more robust.


Use a header file to make you external functions accessible to the compiler. This is not a Python-related problem, it's a common language aspect in C.

my_prototypes.h:

  // declare the prototype. everybody who includes `my_prototypes.h` now knows that it exists.
  PyObject *func_from_other_module(PyObject *self, PyObject *args);

anotherunit.c:

  PyObject *func_from_other_module(PyObject *self, PyObject *args) {
    // actual implementation
  }

mainunit.c:

  #include "my_prototypes.h"

  static PyMethodDef SpamMethods[] = {

    {"func_from_other_module",  func_from_other_module, METH_VARARGS,
      "Blabla"},
    ...
   {NULL, NULL, 0, NULL}        /* Sentinel */
  }

And you are right, if a function is declared static, it can only be used from the file it is contained in. You don't need this - just leave the static out (Basically, you wouldn't even need the header: placing the function declarations at the top of mainunit.c works as well).


So, the way I got this working in the end was to use Cython. Not only did it take about an hour to rewrite the c/python interface (which had previously taken about a day due to all the reference counting rules etc) but it also handles all the build issues for you, and has clear documentation describing exactly which methods will be available from python.

In particular, the documentation chapters I used were the build instructions, how to call C libraries, the language basics and how to cast types, particularly pointers.

For anyone looking to wrap existing complex-structured C code (i.e. anything more than a single file) as a python library, I can highly recommend Cython.

0

精彩评论

暂无评论...
验证码 换一张
取 消