Matt Joiner
Matt Joiner

Reputation: 118540

Prevent automatic type conversion in ctypes callback functions

When wrapping Python functions with a CFUNCTYPE type, I've found that the non-pointer types are automatically converted as though their value attribute was called.

How can I suppress this automatic conversion?

from ctypes import *

funcspec = CFUNCTYPE(c_int, c_int, POINTER(c_int))

@funcspec
def callback(the_int, the_int_p):
    print(vars())
    return 3

print(callback(c_int(1), byref(c_int(2))))

Which produces (python3cfunctype_type_conversion.py):

{'the_int': 1, 'the_int_p': <__main__.LP_c_int object at 0x2671830>}
3

I'd like:

{'the_int': c_int(1), 'the_int_p': <__main__.LP_c_int object at 0x2671830>}
c_int(3)

Upvotes: 6

Views: 780

Answers (2)

Brett Stottlemyer
Brett Stottlemyer

Reputation: 2852

I've been looking at the ctypes code recently, thought I might be able to figure this one out. The c code that does this is in callproc.c (here's the source for 2.7.2).

A relevant comment from the source:

5. If 'converters' are present (converters is a sequence of argtypes' from_param methods), for each item in 'callargs' converter is called and the result passed to ConvParam. If 'converters' are not present, each argument is directly passed to ConvParm.

Which is pretty much what Luke said, so what he gave is probably not a hack.

Upvotes: 1

Luke
Luke

Reputation: 11644

This is a bit of a hack, but it might work for you. Hopefully someone else will chime in with a cleaner way..

from ctypes import *

class c_int_hack(c_int):
    def from_param(self, *args):
        return self

funcspec = CFUNCTYPE(c_int, c_int_hack, POINTER(c_int))

@funcspec
def callback(the_int, the_int_p):
    print(vars())
    print(the_int.value)
    return 3

print(callback(c_int(1), byref(c_int(2))))

..and the output is:

{'the_int': <c_int_hack object at 0xb7478b6c>, 'the_int_p': <__main__.LP_c_long object at 0xb747892c>}
1
3

Upvotes: 3

Related Questions