[Python-Dev] future-proofing vector tables for python APIs: binary-module interoperability

Luke Kenneth Casson Leighton lkcl at lkcl.net
Sun Jan 25 18:34:42 CET 2009


On Sun, Jan 25, 2009 at 3:55 PM, Roumen Petrov
<bugtrack at roumenpetrov.info> wrote:
> Luke Kenneth Casson Leighton wrote:
>>>>
>>>> [SNIP]
>>>> Yes it is enough to encapsulate memory allocation and file functions
>>>> into
>>>> python shared library. The python provide memory allocation functions,
>>>> but
>>>> not all modules use them. File functions are hiden by posixmodule and
>>>> python
>>>> modules can't use them.
>>>
>>>  except ... posixmodule gets renamed to ntmodule .... oh, i see what
>>> you mean: python modules aren't allowed _direct_ access to msvcrtNN's
>>> file functions, they have to go via posixmodule-renamed-to-ntmodule.
>>
>>  .... thinking about this some more...  posixmodule.c is linked (by
>> default) into pythonNN.dll, thus making pythonNN.dll totally dependent
>> on a version of msvcrt.
>
> This is not problem. If python*.dll hide msvcrt and other modules depend
> directly from python*.dll I expect issue to be resolved. i.e. python*.dll to
> be "portable runtime interface".

 yehhhh :)

 well - it looks like i am having success with removing all references
to data e.g. Py_NoneStruct, all of the PyExc_*Warning and
PyExc_*Error, all of the Py*_Types and more.

i'm making sure that macros are heavily used - so that on systems
where data _can_ be accessed through dynamic shared objects, it's done
so.

#if defined(MS_WINDOWS) || defined(__MINGW32__)
/* Define macros for conveniently creating "getter" functions,
 * to avoid restrictions on dlls being unable to access data.
 * see #5056
 */

/* use these for data that is already a pointer */
#define PyAPI_GETHDR(type, obj) \
    PyAPI_FUNC(type) _Py_Get_##obj(void);
#define PyAPI_GETIMPL(type, obj) \
    PyAPI_FUNC(type) _Py_Get_##obj(void) { return (type)obj; }
#define _PYGET(obj) _Py_Get_##obj()

/* use these for data where a pointer (&) to the object is returned
 * e.g. no longer #define Py_None (&Py_NoneStruct) but
 * #define Py_None _PTGETPTR(Py_NoneStruct)
 */
#define PyAPI_GETHDRPTR(type, obj) \
    PyAPI_FUNC(type) _Py_Get_##obj(void);
#define PyAPI_GETIMPLPTR(type, obj) \
    PyAPI_FUNC(type) _Py_Get_##obj(void) { return (type)&obj; }
#define _PYGETPTR(obj) _Py_Get_##obj()

#else

/* on systems where data can be accessed directly in shared modules,
 * as an optimisation, return the object itself, directly.
 */
#define PyAPI_GETFNIMPL(obj) ;
#define PyAPI_GETHDR(type, obj) ;
#define PyAPI_GETIMPL(type, obj) ;
#define PyAPI_GETIMPLPTR(type, obj) ;
#define _PYGET(obj) (obj)
#define _PYGETPTR(obj) (&obj)

#endif /* defined(MS_WINDOWS) || defined(__MINGW32__)*/


as you can see from the Py_None example, on non-dll-based systems, you
get... wow, a macro which returns... exactly what was returned before.

zero impact.

on windows, you end up defining, creating and using a "getter"
function.  two types.  one which returns the object, the other returns
a pointer to the object.

l.


More information about the Python-Dev mailing list