Skip to content

Automatic upcast does not occur for custom classes #74877

Closed as duplicate
Closed as duplicate

Description

@rharke
mannequin
BPO 30692
Nosy @amauryfa, @abalkin, @meadori

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = None
created_at = <Date 2017-06-17.19:29:40.309>
labels = ['ctypes', 'type-bug']
title = 'Automatic upcast does not occur for custom classes'
updated_at = <Date 2017-06-17.19:39:41.287>
user = 'https://bugs.python.org/rharke'

bugs.python.org fields:

activity = <Date 2017-06-17.19:39:41.287>
actor = 'ned.deily'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['ctypes']
creation = <Date 2017-06-17.19:29:40.309>
creator = 'rharke'
dependencies = []
files = []
hgrepos = []
issue_num = 30692
keywords = []
message_count = 1.0
messages = ['296245']
nosy_count = 4.0
nosy_names = ['amaury.forgeotdarc', 'belopolsky', 'meador.inge', 'rharke']
pr_nums = []
priority = 'normal'
resolution = None
stage = None
status = 'open'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue30692'
versions = ['Python 2.7', 'Python 3.6']

Activity

  1. rharke commented on Jun 17, 2017

    rharkemannequin
    MannequinAuthor

    I have noticed that the automatic upcast mechanism which works for
    standard ctypes types does not appear to work for custom types with
    _as_parameter_ defined.

    Consider the following example (written for Mac OS X but just change
    the LoadLibrary call to test on a different OS):

    # -- begin --
    from ctypes import *
    
    libc = cdll.LoadLibrary('/usr/lib/libc.dylib')
    
    class Base(Structure): pass
    class Derived(Base): pass
    class Wrapper(object): pass
    
    printf = libc.printf
    printf.argtypes = [ c_char_p, POINTER(Base) ]
    printf.restype = c_int
    
    derived = Derived()
    derived_ptr = pointer(derived)
    derived_ptr_wrapper = Wrapper()
    derived_ptr_wrapper._as_parameter_ = pointer(derived)
    
    # Case 1 WORKS: Derived* is automatically upcast to Base* and passed to
    #               printf
    printf(b'%p\n', derived_ptr)
    
    # Case 2 WORKS: The Wrapper can be explicitly upcast to a Base* and
    #               passed to printf
    printf(b'%p\n', cast(derived_ptr_wrapper, POINTER(Base)))
    
    # Case 3 FAILS: Automatic upcast does NOT happen with the value in the
    #               Wrapper: 'expected LP_Base instance instead of
    #               LP_Derived'
    printf(b'%p\n', derived_ptr_wrapper)
    # -- end --

    Here we have two types, Base which is a ctypes Structure, and Derived
    which derives from Base. A pointer to Derived can be passed to a
    function that expects a pointer to Base, and it will automatically be
    upcast.

    However, once the Wrapper type is introduced, which simply holds a
    pointer to Derived in its _as_parameter_ attribute, the automatic
    upcast no longer occurs. A manual upcast works, though.

    I believe this may be related to bpo-27803, but that is talking about
    byref() whereas this is related to cast(). Perhaps the internal
    mechanism is the same; certainly it sounds like a similar problem.

    I've tested this in Python 2.7 and 3.6, and the result is the same.

    Not sure if this is a bug or an enhancement request- filing it as
    "behavior" for now since to me, this is something that I expected to
    implicitly work.

    Thanks! - Ranger Harke.

  2. transferred this issue fromon Apr 10, 2022
  3. ZeroIntensity commented on Oct 19, 2026

    @ZeroIntensity
    Member

    Same root cause as #71990, so #159763 should fix it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions