python ctypes garbage collection

1

I am using ctypes to access a c library (it is really c++ code) from python:

class CRMeAnnotationList(object):
def __init__(self):
    self.obj = lib.CRMeAnnotationList_new()de
def __del__(self):
    if self.obj:
        lib.CRMeAnnotationList_destroy(self.obj)
lst = CRMeAnnotationList()

The C code looks like this

extern "C" {__declspec(dllexport) CRMeAnnotationList* CRMeAnnotationList_new() 
                { return new CRMeAnnotationList(); 
                }
            __declspec(dllexport)void CRMeAnnotationList_destroy(CRMeAnnotationList* p)
                {
                if (p)
                    delete p;
                }
            }

This code gives me finished with exit code -1073741819 (0xC0000005)

whereas if I do not destroy the pointer I get 0 as exit code.

Does this mean, that I do not need to destroy that pointer i.e execute the destructor part del in the python code?

python
ctypes
asked on Stack Overflow Jan 6, 2019 by prudnik

1 Answer

1

You are likely running 64-bit Python and haven't set .argtypes and .restype properly.

Example:

test.cpp

#define API __declspec(dllexport) // Windows-specific

extern "C" {

struct CRMeAnnotationList {
    int a;
};

API CRMeAnnotationList* CRMeAnnotationList_new() {
    return new CRMeAnnotationList();
}

API void CRMeAnnotationList_destroy(CRMeAnnotationList* p) {
    if(p)
        delete p;
}

}

test.py

from ctypes import *

lib = CDLL('test')
lib.CRMeAnnotationList_new.argtypes = None
lib.CRMeAnnotationList_new.restype = c_void_p
lib.CRMeAnnotationList_destroy.argtypes = c_void_p,
lib.CRMeAnnotationList_destroy.restype = None

class CRMeAnnotationList:

    def __init__(self):
        print(f'created   {id(self):#x}')
        self.obj = lib.CRMeAnnotationList_new()

    def __del__(self):
        print(f'destroyed {id(self):#x}')
        if self.obj:
            lib.CRMeAnnotationList_destroy(self.obj)

lst = CRMeAnnotationList()

Output:

created   0x2232dfc35c0
destroyed 0x2232dfc35c0

Output when .argtypes and .restype lines are commented out:

created   0x1c98e8f35c0
destroyed 0x1c98e8f35c0
Exception ignored in: <function CRMeAnnotationList.__del__ at 0x000001C98E9176A8>
Traceback (most recent call last):
  File "C:\Users\metolone\Desktop\test.py", line 16, in __del__
OSError: exception: access violation reading 0xFFFFFFFF8C6CABCF

Note the address of the access violation. It is a 32-bit value sign-extended to 64-bits.

answered on Stack Overflow Jan 6, 2019 by Mark Tolonen

User contributions licensed under CC BY-SA 3.0