r'''

This tests the '_objects' attribute of ctypes instances.  '_objects'

holds references to objects that must be kept alive as long as the

ctypes instance, to make sure that the memory buffer is valid.



WARNING: The '_objects' attribute is exposed ONLY for debugging ctypes itself,

it MUST NEVER BE MODIFIED!



'_objects' is initialized to a dictionary on first use, before that it

is None.



Here is an array of string pointers:



>>> from ctypes import *

>>> array = (c_char_p * 5)()

>>> print array._objects

None

>>>



The memory block stores pointers to strings, and the strings itself

assigned from Python must be kept.



>>> array[4] = 'foo bar'

>>> array._objects

{'4': 'foo bar'}

>>> array[4]

'foo bar'

>>>



It gets more complicated when the ctypes instance itself is contained

in a 'base' object.



>>> class X(Structure):

...     _fields_ = [("x", c_int), ("y", c_int), ("array", c_char_p * 5)]

...

>>> x = X()

>>> print x._objects

None

>>>



The'array' attribute of the 'x' object shares part of the memory buffer

of 'x' ('_b_base_' is either None, or the root object owning the memory block):



>>> print x.array._b_base_ # doctest: +ELLIPSIS

<ctypes.test.test_objects.X object at 0x...>

>>>



>>> x.array[0] = 'spam spam spam'

>>> x._objects

{'0:2': 'spam spam spam'}

>>> x.array._b_base_._objects

{'0:2': 'spam spam spam'}

>>>



'''



import unittest, doctest, sys



import ctypes.test.test_objects



class TestCase(unittest.TestCase):

    if sys.hexversion > 0x02040000:

        # Python 2.3 has no ELLIPSIS flag, so we don't test with this

        # version:

        def test(self):

            doctest.testmod(ctypes.test.test_objects)



if __name__ == '__main__':

    if sys.hexversion > 0x02040000:

        doctest.testmod(ctypes.test.test_objects)

