Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Wrapping a C lib and reference counting

Reply
Thread Tools

Wrapping a C lib and reference counting

 
 
Mosfet
Guest
Posts: n/a
 
      05-28-2009
Hi,

I would like to wrapp a C library I wrote used to access address book on
windows mobile and basically here is how it is designed :

typedef void GDAddrBook;
typedef void GDAbItem;


GYNOID_API ErrorCode
GDAddrBook_Open(OsHandle osParam, GDAddrBook** gppAddrbook);

GYNOID_API ErrorCode
GDAddrBook_Close(GDAddrBook* gpAddrbook);

GYNOID_API ErrorCode
GDAddrBook_GetCount(GDAddrBook* gpAddrbook, int* ulCount);

GYNOID_API ErrorCode
GDAbItem_Release(GDAbItem* gpContact);

GYNOID_API ErrorCode
GDAddrBook_GetItem(GDAddrBook* gpAddrbook, int iIndex, GDAbItem**
gppAbItem);

GYNOID_API void*
GDAbItem_GetProperty(GDAbItem* gpContact, EAbItemProp eContactProp);


So A typical use to get the first addrbook item would be (simple case
with no error checking):

GDCTSTR lpFirstName;
GDAddrBook* gdAb;
GDAbItem* gdAbItem;

GDAddrBook_Open(0, &gdAb);
GDAddrBook_GetItem(gdAb, 0, &gdAbItem);

lpFirstName = (GDCTSTR) GDAbItem_GetProperty(gdAbItem, eAbFirstName);

// Now we release our two "objects"
GDAbItem_Release(gdAbItem);
GDAddrBook_Release(gdAb)


Now I would like to provide a C++ wrapper where C++ objects would hold
GDxxxx pointers and would call Gdxxxx_Release automatically

AddrBook ab;
AddrBookItem abItem;

abItem = ab.getItem(0);
GDString = abItem.getProperty(eAbFirstName);

The problem is about

AddrBookItem AddrBook::getItem(int iIndex)
{
GDAbItem* gpAbItem = NULL;
GDAddrBook_GetItem(m_gpAb, iIndex, &gpAbItem);
AddrBookItem abItem(gpAbItem);

return abItem;
}


Because If I write something like that, my local abItem will be
destroyed and will call its destructor, so my internal pointer will be
released.
The only way I can see is to use reference counting but is it the only way ?

Another approach would be to use reference like that :

ab.getItem(0, abItem );

but what is the best way and how to solve my issues ?




















 
Reply With Quote
 
 
 
 
Maxim Yegorushkin
Guest
Posts: n/a
 
      05-28-2009
On May 28, 2:00*pm, Mosfet <(E-Mail Removed)> wrote:
> Hi,
>
> I would like to wrapp a C library I wrote used to access address book on
> windows mobile and basically here is how it is designed :
>
> typedef void GDAddrBook;
> typedef void GDAbItem;


These seem to be rather long new names for void with little utility.

Probably, you want to add some type safety to justify your long names:

typedef struct GDAddrBookTag* GDAddrBook;
typedef struct GDAbItemTag* GDAbItem;

This way you can't use GDAddrBook in place of GDAbItem and vice versa.

> GYNOID_API ErrorCode * *
> GDAddrBook_Open(OsHandle osParam, GDAddrBook** gppAddrbook);
>
> GYNOID_API ErrorCode * *
> GDAddrBook_Close(GDAddrBook* gpAddrbook);
>
> GYNOID_API ErrorCode * *
> GDAddrBook_GetCount(GDAddrBook* gpAddrbook, int* ulCount);
>
> GYNOID_API ErrorCode * *
> GDAbItem_Release(GDAbItem* gpContact);
>
> GYNOID_API ErrorCode * *
> GDAddrBook_GetItem(GDAddrBook* gpAddrbook, int iIndex, GDAbItem**
> gppAbItem);
>
> GYNOID_API void* * * * * * * * *
> GDAbItem_GetProperty(GDAbItem* gpContact, EAbItemProp eContactProp);
>
> So A typical use to get the first addrbook item would be (simple case
> with no error checking):
>
> GDCTSTR lpFirstName;
> GDAddrBook* gdAb;
> GDAbItem* gdAbItem;
>
> GDAddrBook_Open(0, &gdAb);
> GDAddrBook_GetItem(gdAb, 0, &gdAbItem);
>
> lpFirstName = (GDCTSTR) GDAbItem_GetProperty(gdAbItem, eAbFirstName);
>
> // Now we release our two "objects"
> GDAbItem_Release(gdAbItem);
> GDAddrBook_Release(gdAb)
>
> Now I would like to provide a C++ wrapper where C++ objects would hold
> GDxxxx pointers and would call Gdxxxx_Release automatically
>
> AddrBook ab;
> AddrBookItem abItem;
>
> abItem = ab.getItem(0);
> GDString = abItem.getProperty(eAbFirstName);
>
> The problem is about
>
> AddrBookItem AddrBook::getItem(int iIndex)
> {
> * * * GDAbItem* gpAbItem = NULL;
> * * * GDAddrBook_GetItem(m_gpAb, iIndex, &gpAbItem);
> * * * AddrBookItem abItem(gpAbItem);
>
> * * * return abItem;
> }
>
> Because If I write something like that, my local abItem will be
> destroyed and will call its destructor, so my internal pointer will be
> released.
> The only way I can see is to use reference counting but is it the only way ?


Reference counting is the easiest here.

Another way is to be as fancy as std::auto_ptr<> is. I.e. transfer the
ownership of the handle on copy construction and assignment. The
downside is that such fancy objects can not be stored in containers
and one has to be extra careful to avoid accidental copying.

In C++0x you would solve this elegantly by using move constructors.
http://en.wikipedia.org/wiki/C%2B%2B...move_semantics

--
Max
 
Reply With Quote
 
 
 
 
Michael Doubez
Guest
Posts: n/a
 
      05-28-2009
On May 28, 3:00*pm, Mosfet <(E-Mail Removed)> wrote:
> Hi,
>
> I would like to wrapp a C library I wrote used to access address book on
> windows mobile and basically here is how it is designed :
>
> typedef void GDAddrBook;
> typedef void GDAbItem;
>
> GYNOID_API ErrorCode * *
> GDAddrBook_Open(OsHandle osParam, GDAddrBook** gppAddrbook);
>
> GYNOID_API ErrorCode * *
> GDAddrBook_Close(GDAddrBook* gpAddrbook);
>
> GYNOID_API ErrorCode * *
> GDAddrBook_GetCount(GDAddrBook* gpAddrbook, int* ulCount);
>
> GYNOID_API ErrorCode * *
> GDAbItem_Release(GDAbItem* gpContact);
>
> GYNOID_API ErrorCode * *
> GDAddrBook_GetItem(GDAddrBook* gpAddrbook, int iIndex, GDAbItem**
> gppAbItem);
>
> GYNOID_API void* * * * * * * * *
> GDAbItem_GetProperty(GDAbItem* gpContact, EAbItemProp eContactProp);
>
> So A typical use to get the first addrbook item would be (simple case
> with no error checking):
>
> GDCTSTR lpFirstName;
> GDAddrBook* gdAb;
> GDAbItem* gdAbItem;
>
> GDAddrBook_Open(0, &gdAb);
> GDAddrBook_GetItem(gdAb, 0, &gdAbItem);
>
> lpFirstName = (GDCTSTR) GDAbItem_GetProperty(gdAbItem, eAbFirstName);
>
> // Now we release our two "objects"
> GDAbItem_Release(gdAbItem);
> GDAddrBook_Release(gdAb)
>
> Now I would like to provide a C++ wrapper where C++ objects would hold
> GDxxxx pointers and would call Gdxxxx_Release automatically
>
> AddrBook ab;
> AddrBookItem abItem;
>
> abItem = ab.getItem(0);
> GDString = abItem.getProperty(eAbFirstName);
>
> The problem is about
>
> AddrBookItem AddrBook::getItem(int iIndex)
> {
> * * * GDAbItem* gpAbItem = NULL;
> * * * GDAddrBook_GetItem(m_gpAb, iIndex, &gpAbItem);
> * * * AddrBookItem abItem(gpAbItem);
>
> * * * return abItem;
>
> }
>
> Because If I write something like that, my local abItem will be
> destroyed and will call its destructor, so my internal pointer will be
> released.
> The only way I can see is to use reference counting but is it the only way ?


You could also duplicate it at each copy.

For your function, you can also create an artefact AddrBookItemRef
that destroy its ressource if it was not used by a AddrBookItem.

class AddrBookItem
{
//...
class AddrBookItemRef
{
public:
AddrBookItemRef(GDAbItem*p=NULL)tr(p){}
AddrBookItemRef(const AddrBookItemRef& r)tr(p.release()){}
~AddrBookItemRef(){if(ptr)GDAbItem_Release(ptr);}
private:
GDAbItem* release()const{GDAbItem*p=ptr;ptr=NULL;return p;}
mutable GDAbItem* ptr;
};

AddrBookItem(const AddrBookItemRef& r)
{
internal=r.release();
}
//...
};

You would have to decide what to do with copy operator for
AddrBookItemRef (I would say forbid it).
If you want to allow it, you can directly return a
std::auto_ptr<GDAbItem>.

You could also use garbage collection

> Another approach would be to use reference like that :
>
> * ab.getItem(0, abItem );
>
> but what is the best way and how to solve my issues ?


Duplicating your data doesn't seem a big deal unless you can find
another persistence root.

--
Michael
 
Reply With Quote
 
Mosfet
Guest
Posts: n/a
 
      05-28-2009
Michael Doubez a écrit :
> On May 28, 3:00 pm, Mosfet <(E-Mail Removed)> wrote:
>> Hi,
>>
>> I would like to wrapp a C library I wrote used to access address book on
>> windows mobile and basically here is how it is designed :
>>
>> typedef void GDAddrBook;
>> typedef void GDAbItem;
>>
>> GYNOID_API ErrorCode
>> GDAddrBook_Open(OsHandle osParam, GDAddrBook** gppAddrbook);
>>
>> GYNOID_API ErrorCode
>> GDAddrBook_Close(GDAddrBook* gpAddrbook);
>>
>> GYNOID_API ErrorCode
>> GDAddrBook_GetCount(GDAddrBook* gpAddrbook, int* ulCount);
>>
>> GYNOID_API ErrorCode
>> GDAbItem_Release(GDAbItem* gpContact);
>>
>> GYNOID_API ErrorCode
>> GDAddrBook_GetItem(GDAddrBook* gpAddrbook, int iIndex, GDAbItem**
>> gppAbItem);
>>
>> GYNOID_API void*
>> GDAbItem_GetProperty(GDAbItem* gpContact, EAbItemProp eContactProp);
>>
>> So A typical use to get the first addrbook item would be (simple case
>> with no error checking):
>>
>> GDCTSTR lpFirstName;
>> GDAddrBook* gdAb;
>> GDAbItem* gdAbItem;
>>
>> GDAddrBook_Open(0, &gdAb);
>> GDAddrBook_GetItem(gdAb, 0, &gdAbItem);
>>
>> lpFirstName = (GDCTSTR) GDAbItem_GetProperty(gdAbItem, eAbFirstName);
>>
>> // Now we release our two "objects"
>> GDAbItem_Release(gdAbItem);
>> GDAddrBook_Release(gdAb)
>>
>> Now I would like to provide a C++ wrapper where C++ objects would hold
>> GDxxxx pointers and would call Gdxxxx_Release automatically
>>
>> AddrBook ab;
>> AddrBookItem abItem;
>>
>> abItem = ab.getItem(0);
>> GDString = abItem.getProperty(eAbFirstName);
>>
>> The problem is about
>>
>> AddrBookItem AddrBook::getItem(int iIndex)
>> {
>> GDAbItem* gpAbItem = NULL;
>> GDAddrBook_GetItem(m_gpAb, iIndex, &gpAbItem);
>> AddrBookItem abItem(gpAbItem);
>>
>> return abItem;
>>
>> }
>>
>> Because If I write something like that, my local abItem will be
>> destroyed and will call its destructor, so my internal pointer will be
>> released.
>> The only way I can see is to use reference counting but is it the only way ?

>
> You could also duplicate it at each copy.
>
> For your function, you can also create an artefact AddrBookItemRef
> that destroy its ressource if it was not used by a AddrBookItem.
>
> class AddrBookItem
> {
> //...
> class AddrBookItemRef
> {
> public:
> AddrBookItemRef(GDAbItem*p=NULL)tr(p){}
> AddrBookItemRef(const AddrBookItemRef& r)tr(p.release()){}
> ~AddrBookItemRef(){if(ptr)GDAbItem_Release(ptr);}
> private:
> GDAbItem* release()const{GDAbItem*p=ptr;ptr=NULL;return p;}
> mutable GDAbItem* ptr;
> };
>
> AddrBookItem(const AddrBookItemRef& r)
> {
> internal=r.release();
> }
> //...
> };
>
> You would have to decide what to do with copy operator for
> AddrBookItemRef (I would say forbid it).
> If you want to allow it, you can directly return a
> std::auto_ptr<GDAbItem>.
>
> You could also use garbage collection
>
>> Another approach would be to use reference like that :
>>
>> ab.getItem(0, abItem );
>>
>> but what is the best way and how to solve my issues ?

>
> Duplicating your data doesn't seem a big deal unless you can find
> another persistence root.
>
> --
> Michael


Finally I have adopted an hybrid approach, now all my GD object are
inheriting from GDObject;

typedef struct _GDObject
{
unsigned long cRefs;
} GDObject;


typedef GDObject GDAddrBook;
typedef GDObject GDAbItem;

I have added two functions :

unsigned long
GDObject_AddRef(GDObject* gdObject)
{
return 0;
}

unsigned long
GDObject_Release(GDObject* gdObject)
{
return 0;
}

and now when object is copied I increment counter.
When it's 0 it's deallocated.







 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Reference counting and API (const reference vs pointer oriented) mathieu C++ 8 08-31-2008 09:05 AM
difference between libboost_regex-mt-gd-1_33_1.lib and boost_regex-mt-gd-1_33_1.lib ideal.black@gmail.com C++ 3 09-30-2007 06:54 AM
Diff betw common/lib and shared/lib in Tomcat James Yong Java 0 09-12-2005 02:36 AM
counting up instead of counting down edwardfredriks Javascript 6 09-07-2005 03:30 PM
[ANN] Anonymous CVS repository of lib/csv and lib/soap4r suspendedagain NAKAMURA, Hiroshi Ruby 0 07-06-2004 08:19 AM



Advertisments