This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author vinay.sajip
Recipients Igor Kudrin, christian.heimes, doko, eryksun, mark.dickinson, meador.inge, paul.moore, steve.dower, tim.golden, vinay.sajip, zach.ware
Date 2017-02-19.06:09:07
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1487484548.53.0.548046012659.issue29565@psf.upfronthosting.co.za>
In-reply-to
Content
When adding the fix for #20160 I had added a test involving passing a struct by value to a Python callback. I modified that test to update the struct in the callback, and check that the passed-in struct hadn't changed.

    def test_callback_large_struct(self):
        class Check: pass

        class X(Structure):
            _fields_ = [
                ('first', c_ulong),
                ('second', c_ulong),
                ('third', c_ulong),
            ]

        def callback(check, s):
            check.first = s.first
            check.second = s.second
            check.third = s.third
            # See issue #29565.
            # The structure should be passed by value, so
            # any changes to it should not be reflected in
            # the value passed
            s.first = s.second = s.third = 0x0badf00d

        check = Check()
        s = X()
        s.first = 0xdeadbeef
        s.second = 0xcafebabe
        s.third = 0x0bad1dea

        CALLBACK = CFUNCTYPE(None, X)
        dll = CDLL(_ctypes_test.__file__)
        func = dll._testfunc_cbk_large_struct
        func.argtypes = (X, CALLBACK)
        func.restype = None
        # the function just calls the callback with the passed structure
        func(s, CALLBACK(functools.partial(callback, check)))
        self.assertEqual(check.first, s.first)
        self.assertEqual(check.second, s.second)
        self.assertEqual(check.third, s.third)
        self.assertEqual(check.first, 0xdeadbeef)
        self.assertEqual(check.second, 0xcafebabe)
        self.assertEqual(check.third, 0x0bad1dea)
        # See issue #29565.
        # Ensure that the original struct is unchanged.
        self.assertEqual(s.first, check.first)
        self.assertEqual(s.second, check.second)
        self.assertEqual(s.third, check.third)

The changed test still passes, so it looks like ctypes makes a copy when passing from C to a Python callback, but not when passing from Python to C.
History
Date User Action Args
2017-02-19 06:09:08vinay.sajipsetrecipients: + vinay.sajip, doko, paul.moore, mark.dickinson, christian.heimes, tim.golden, meador.inge, zach.ware, eryksun, steve.dower, Igor Kudrin
2017-02-19 06:09:08vinay.sajipsetmessageid: <1487484548.53.0.548046012659.issue29565@psf.upfronthosting.co.za>
2017-02-19 06:09:08vinay.sajiplinkissue29565 messages
2017-02-19 06:09:07vinay.sajipcreate