M
Mosfet
Hi,
I ma developping a small framework exporting C functions but behind the
scene I am manipulating C++ objects. Memory management relies on
reference count and the base C "object" is called GDObject and is
actually a structure with a counter.
///////////////////////////////////////////////////////
// Public declaration for GDObject used to handle "object" life
__BEGIN_C_DECLS
typedef struct _GDObject GDObject;
typedef struct _GDObject
{
long cRefs;
} GDObject;
#define GDObject_AddRef(x) _GDObject_AddRef((GDObject*) (x));
#define GDObject_Release(x) _GDObject_Release((GDObject*) (x));
GYNOID_API long
_GDObject_AddRef(GDObject* gdObject);
GYNOID_API long
_GDObject_Release(GDObject* gdObject);
__END_C_DECLS
///////////////////////////////////////////////////////
//Private implementation of GDObject :
....
long
_GDObject_Release(GDObject* gdObject)
{
LONG lRef;
if (!gdObject )
return 0;
if (gdObject->cRefs == 1)
{
lRef = 0;
gdObject->cRefs = 0;
}
else
{
lRef = InterlockedDecrement(&(gdObject->cRefs));
}
if (lRef == 0)
{
delete gdObject;
}
return (ULONG)lRef;
}
So now let's consider the address book api defined like this :
// Public declaration
typedef GDObject GDAddrBook;
GYNOID_API ErrorCode
GDAddrBook_Alloc(GDAddrBook** gppAddrbook);
GYNOID_API ErrorCode
GDAddrBook_Init(GDAddrBook* gpAddrbook, OsHandle osParam);
// Private implementation
struct os_addrbook : public GDObject
{
os_addrbook()
{
cRefs = 1;
}
~os_addrbook()
{
...
}
...
};
ErrorCode
OS_GDAddrBook_Alloc(GDAddrBook** gppAddrbook)
{
if (!gppAddrbook)
return E_INVALIDARG;
os_addrbook* pAddrBook = new os_addrbook;
if (pAddrBook)
{
*gppAddrbook = (GDAddrBook*)pAddrBook;
return ERROR_SUCCESS;
}
return E_OUTOFMEMORY;
}
And finally here is a sample app :
GDAddrBook* pAddrBook = NULL;
if (!GDAddrBook_Alloc(&pAddrBook) &&
!GDAddrBook_Init(pAddrBook, 0) )
{
...
}
GDObject_Release(pAddrBook);
So when user call GDAddrBook_Alloc a structure(os_addrbook) inheriting
from the C GDObject structure is allocated and casted into a
GDAddrBook*( typedef for a GDObject*) and then returned to caller.
Then when GDObject_Release is called delete is called on the pointer
casted back to a GDObject*
In this case can delete work knowing that GDObject is actually a C
structure and thus there is no virtual destructor ?
So to sum up :
I allocate an object inheriting from GDObject(C struct) -> returned as a
GDAddrBook*(typedef for a GDObject*) to caller and then when I call
GDObject_Release pointer is cast to GDObject* and then delete is called
on it.
Can it work ?
I ma developping a small framework exporting C functions but behind the
scene I am manipulating C++ objects. Memory management relies on
reference count and the base C "object" is called GDObject and is
actually a structure with a counter.
///////////////////////////////////////////////////////
// Public declaration for GDObject used to handle "object" life
__BEGIN_C_DECLS
typedef struct _GDObject GDObject;
typedef struct _GDObject
{
long cRefs;
} GDObject;
#define GDObject_AddRef(x) _GDObject_AddRef((GDObject*) (x));
#define GDObject_Release(x) _GDObject_Release((GDObject*) (x));
GYNOID_API long
_GDObject_AddRef(GDObject* gdObject);
GYNOID_API long
_GDObject_Release(GDObject* gdObject);
__END_C_DECLS
///////////////////////////////////////////////////////
//Private implementation of GDObject :
....
long
_GDObject_Release(GDObject* gdObject)
{
LONG lRef;
if (!gdObject )
return 0;
if (gdObject->cRefs == 1)
{
lRef = 0;
gdObject->cRefs = 0;
}
else
{
lRef = InterlockedDecrement(&(gdObject->cRefs));
}
if (lRef == 0)
{
delete gdObject;
}
return (ULONG)lRef;
}
So now let's consider the address book api defined like this :
// Public declaration
typedef GDObject GDAddrBook;
GYNOID_API ErrorCode
GDAddrBook_Alloc(GDAddrBook** gppAddrbook);
GYNOID_API ErrorCode
GDAddrBook_Init(GDAddrBook* gpAddrbook, OsHandle osParam);
// Private implementation
struct os_addrbook : public GDObject
{
os_addrbook()
{
cRefs = 1;
}
~os_addrbook()
{
...
}
...
};
ErrorCode
OS_GDAddrBook_Alloc(GDAddrBook** gppAddrbook)
{
if (!gppAddrbook)
return E_INVALIDARG;
os_addrbook* pAddrBook = new os_addrbook;
if (pAddrBook)
{
*gppAddrbook = (GDAddrBook*)pAddrBook;
return ERROR_SUCCESS;
}
return E_OUTOFMEMORY;
}
And finally here is a sample app :
GDAddrBook* pAddrBook = NULL;
if (!GDAddrBook_Alloc(&pAddrBook) &&
!GDAddrBook_Init(pAddrBook, 0) )
{
...
}
GDObject_Release(pAddrBook);
So when user call GDAddrBook_Alloc a structure(os_addrbook) inheriting
from the C GDObject structure is allocated and casted into a
GDAddrBook*( typedef for a GDObject*) and then returned to caller.
Then when GDObject_Release is called delete is called on the pointer
casted back to a GDObject*
In this case can delete work knowing that GDObject is actually a C
structure and thus there is no virtual destructor ?
So to sum up :
I allocate an object inheriting from GDObject(C struct) -> returned as a
GDAddrBook*(typedef for a GDObject*) to caller and then when I call
GDObject_Release pointer is cast to GDObject* and then delete is called
on it.
Can it work ?