Regarding shared (dynamic) libraries I am have only used Windows DLLs.
Unix shared libraries are similar.
Michael George wrote:
The part I was and am still a bit confused about is name clashes. If
I understand correctly, python extension modules are supposed to only
export the initmodule method in order to avoid name clashes, which is
why the docs say everything should be static. But if bitmask is
linked in to the module, then won't it's functions be exported? If
not, then is it possible for me to call them, or do I need to link
bitmask into my code as well? And how is bitmask different than SDL
in terms of how it's linked, if at all?
Name clashes were a concern in the past when extension modules were
statically linked to the Python interpreter, as was necessary with DOS.
I assume no modern operating system requires this, so name clashes are
no longer an issue. (See below.) If anyone is still statically linking
the Pygame extension modules they haven't complained about name
conflicts yet. Besides, all the bitmask names are mangled with a prefix.
As to accessing the bitmask functions it depends on what you want. See
below.
There is no difference between bitmask and SDL when it comes to name
clashes. SDL function names are resolved by the linker at build time,
just as with bitmask. SDL functions appear in the mask namespace just as
bitmask functions do. See below.
Sorry, I feel like I'm saying a bunch of nonsense, but I'm having a
hard time making sense of all this dynamic linking stuff.
Shared (dynamic) libraries are somewhat like programs. Just as with a
program, non-static functions and global variables can be local to the
library. But where as a program has a single entry point, a main
function, a shared library can have many. These are the exported
functions and variables of the library. They form the API. Only these
can be directly accessed by other programs or shared libraries. For
Windows shared libraries (Dynamic Link Libraries or DLLs) the linker
has to be told which non-static functions and global variables get
exported. Everything else remains local to the DLL. For Unix shared
libraries I believe all non-static functions and global variables are
exported by default. I think gcc has ways around this though. But for
Python extension modules this is not a problem.
There are two ways to use a shared library. The first is to load the
library dynamically during program execution. Explicit system calls are
made to load the library and get pointers to its exported functions and
data. This is how the Python interpreter loads extension modules. No
name conflicts between extension modules are possible in this case. The
ctypes package, introduced in Python 2.5, wraps the dynamic load
mechanism, so any shared library is accessible from within Python.
The second way to use a shared library is to have the program loader do
the linking at startup. An import library, a proxy to the shared
library, stands in for the library when building a program. The import
library looks just like any static module. Exported functions and data
look just like non-static functions and global variables to the program.
So name clashes are possible with other non-static names in the program.
Exported names are resolved dynamically at program load time rather than
statically at build time. A shared library is loaded only once, when the
first program that uses it is loaded. Other programs share the library's
memory image. This is how mask and other Pygame extension modules link
to SDL.
I don't suggest making bitmask a shared library. The only shared
libraries Python's distutils knows how to build are extension modules.
What I'm doing now is adding a CObject to the mask module for the
PyMask_Type, and then compiling my code against bitmask.h (which I'm
leaving as-is) and mask.h (which looks like some of the other header
files, and exports a C API with a bunch of #defines). So I'm assuming
I'll need to use CObjects to get at stuff in mask.c (the Type in
particular), but I can link directly to the stuff in bitmask.
If you are just extending the mask module itself then the bitmask
functions will be visible to your code. Just add any new C files to the
mask entry in Setup.in. They will be compiled and linked to mask and
bitmask automatically. Remember to run config.py after any changes to
Setup.in. Name the non-static functions with a prefix like bitmap_. Any
new Python functions go into mask.c itself and remain static.
If you are adding a new extension module then the simplest solution is
to just include bitmask.c in that module as well. If you are concerned
about name clashes then copy the bitmask.c file as bitmask2.c and rename
the functions: bitmap2_* maybe. Also unused code can be removed. The
third option is to do as you suggest and export pointers to mask's
bitmask functions using the PyCObject mechanism.
On an unrelated note, I'm looking at font.h as an example for
exporting the api, and I was wondering in the import_pygame_font why
the code does a memcpy instead of just changing the PyFONT_C_API
pointer. Isn't there a danger of the memcpy stomping on something
else, since it's copying 3 things into a 1-element array?
PyFONT_C_API is an array of PYGAMEAPI_FONT_NUMSLOT, or 3, void pointers.
The {NULL} initializer is valid for C99 and makes all array entries
NULL. For C90 I don't know, but suspect it is invalid.
Lenard Lindstrom wrote:
Hi Michael,
bitmask.c is statically linked to mask.c as an object file. On
Windows the distutils package ensures only the initmask function is
exported as an entry point into the mask.pyd DLL. Unix dynamic
libraries may be more liberal as to what is exported, but Python will
only directly call the module initialization function, so no problem.
Setup.in controls extension builds. This is like a make file. Each
extension module, like mask, has its own line, or dependency entry. A
new C module can be added to an extension module by adding its source
file to an extension module entry. Be sure to run config.py afterward
to build the Setup file used by setup.py.
Lenard
Michael George wrote:
Greetings,
[snip]
I'd be happy to spend some time and submit a patch, but I'm not
quite sure how it should work. Should mask.c access the bitmask.c
functions through the exported function table? Should mask.c just
#include bitmask.c? Any thoughts?
[from another post in this thread]
>
> Understanding the build system(s) is a bit daunting.
--
Lenard Lindstrom
<[EMAIL PROTECTED]>