Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Public/private in C

Reply
Thread Tools

Public/private in C

 
 
jacob navia
Guest
Posts: n/a
 
      03-21-2010
As you may have noticed, when I proposed the iterator object I splitted
the object into a public part (the first 3 fields) an an undisclosed
part specific to each iterator.

This inheritance implementation looks like this:

In the header file:

typedef struct PublicStruct {
// public fields
} Public;

In the implementation file (.c) we do:

typedef struct Inherited {
Public p;
// follow the private fields
} Private;

The interface for all functions is just the public structure:

void fn1(Public *);
void fn2(Public *);

The implementation of fn1 however, does this:

void fn1(Public *p) {
Private *pri = (Private *)p;

// Work with the private struct.
// It is assumed that the pointer
// handed down is actually a private
// pointer

}

Obviously this doesn't have any compiler support
but works quite well in practice. You can add a
"magic" number somewhere in the private struct
in the debug version to catch mistakes when passing
the structures.

Obviously you aren't supposed to copy the public object since you do not
know what is behind. A way to avoid that would be to add a VLA:

typedef struct PublicStruct {
// public fields
// ...
// private fields follow:
char private[];
} Public;


YES I KNOW.

C++/Java/C# do this MUCH better, but they have other drawbacks
that make a pure C solution MUCH better. Thank you.
 
Reply With Quote
 
 
 
 
Ian Collins
Guest
Posts: n/a
 
      03-21-2010
On 03/22/10 11:20 AM, jacob navia wrote:
> As you may have noticed, when I proposed the iterator object I splitted
> the object into a public part (the first 3 fields) an an undisclosed
> part specific to each iterator.


<snip example>

> Obviously this doesn't have any compiler support
> but works quite well in practice. You can add a
> "magic" number somewhere in the private struct
> in the debug version to catch mistakes when passing
> the structures.
>
> Obviously you aren't supposed to copy the public object since you do not
> know what is behind. A way to avoid that would be to add a VLA:
>
> typedef struct PublicStruct {
> // public fields
> // ...
> // private fields follow:
> char private[];


This isn't a VLA, its an example of the "struct hack".

> } Public;


You can still copy these. It's not a good idea, but there's nothing to
prevent the copy.

> YES I KNOW.
>
> C++/Java/C# do this MUCH better, but they have other drawbacks
> that make a pure C solution MUCH better. Thank you.


In this instance, please elaborate!

--
Ian Collins
 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      03-21-2010
Ian Collins <(E-Mail Removed)> writes:
> On 03/22/10 11:20 AM, jacob navia wrote:

[...]
>> typedef struct PublicStruct {
>> // public fields
>> // ...
>> // private fields follow:
>> char private[];

>
> This isn't a VLA, its an example of the "struct hack".
>
>> } Public;

[...]

More precisely, it's a "flexible array member", C99's replacement for
the "struct hack".

Incidentally, jacob's declaration for the struct was properly
indented, but the indentation vanished in Ian's followup, probably
because of the use of tabs. At least for Usenet posts, spaces are
better than tabs for indentation, since news software doesn't always
deal sanely with tabs.

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Hamiral
Guest
Posts: n/a
 
      03-21-2010
jacob navia wrote:
> As you may have noticed, when I proposed the iterator object I splitted
> the object into a public part (the first 3 fields) an an undisclosed
> part specific to each iterator.


Interesting.
Do you have something similar for inheritance, or... polymorphism ? That
would be great

Ham
 
Reply With Quote
 
ImpalerCore
Guest
Posts: n/a
 
      03-22-2010
On Mar 21, 6:20*pm, jacob navia <(E-Mail Removed)> wrote:
> As you may have noticed, when I proposed the iterator object I splitted
> the object into a public part (the first 3 fields) an an undisclosed
> part specific to each iterator.
>
> This inheritance implementation looks like this:
>
> In the header file:
>
> typedef struct PublicStruct {
> * * * * // public fields
>
> } Public;
>
> In the implementation file (.c) we do:
>
> typedef struct Inherited {
> * * * * Public p;
> * * * * // follow the private fields
>
> } Private;
>
> The interface for all functions is just the public structure:
>
> void fn1(Public *);
> void fn2(Public *);
>
> The implementation of fn1 however, does this:
>
> void fn1(Public *p) {
> * * * * Private *pri = (Private *)p;
>
> * * * * // Work with the private struct.
> * * * * // It is assumed that the pointer
> * * * * // handed down is actually a private
> * * * * // pointer
>
> }
>
> Obviously this doesn't have any compiler support
> but works quite well in practice. You can add a
> "magic" number somewhere in the private struct
> in the debug version to catch mistakes when passing
> the structures.
>
> Obviously you aren't supposed to copy the public object since you do not
> know what is behind. A way to avoid that would be to add a VLA:
>
> typedef struct PublicStruct {
> * * * * // public fields
> * * * * // ...
> * * * * // private fields follow:
> * * * * char private[];
>
> } Public;
>
> YES I KNOW.
>
> C++/Java/C# do this MUCH better, but they have other drawbacks
> that make a pure C solution MUCH better. Thank you.


Personally I think implementing some public/private separation is
outside the scope of C. Grafting this OO paradigm into C is purely
arbitrary at best, confusing and complex at worst. C wants people to
get their hands dirty, and doesn't do a whole lot to protect them.

Again, you say a pure C solution is MUCH better, but I haven't seen a
really cool use-case that says "Yeah, I want to try it out!". If I
wanted to make something private in C, I'd just give the "private"
members a hideously long name so that most people will just be annoyed/
bored to type it out and use the "public" parts

Best regards,
John D.
 
Reply With Quote
 
jacob navia
Guest
Posts: n/a
 
      03-22-2010
ImpalerCore a écrit :

> Personally I think implementing some public/private separation is
> outside the scope of C. Grafting this OO paradigm into C is purely
> arbitrary at best, confusing and complex at worst. C wants people to
> get their hands dirty, and doesn't do a whole lot to protect them.
>


Well, as you may have noticed, I proposed a common iterator object for
iterating through ANY container in my library. Obviously that object
can't be a SINGLE type, it must be several since it must have the specific
knowledge of each container, AND it must offer a COMMON interface, so user
code is independent of the container.

It is not just "a matter of protecting people from themselves", it is
just that is impossible to make a COMMON type for all container iterators
if each iterator exposes its interface.

The solution is then, to define a common interface with a few
function pointers that is shared by all containers. User code uses that
interface

typedef struct _iterator {
void (*Getnext)(structb_iterator *);
// Some other public function pointers
char private[]; // Document that this is a variable length structure
} Iterator;

In the file of the container implementation (say list.c) I
define

typedef struct tagListIterator {
Iterator it;
// Private fields follow
List *list;
unsigned timestamp;
// etc
} ListIterator;

Now, I can define

static void *GetNext(Iterator *it)
{
ListIterator *li = (ListIterator *)it;

// And now I can use the private fields
// in this implementation.
}

The advantage of this is that I can EXTEND a public structure with private
parts, something similar to simple inheritance in C.

> Again, you say a pure C solution is MUCH better, but I haven't seen a
> really cool use-case that says "Yeah, I want to try it out!".


When you write a library, it is very handy since it allows to present a common
interface for a set of different objects

> If I
> wanted to make something private in C, I'd just give the "private"
> members a hideously long name so that most people will just be annoyed/
> bored to type it out and use the "public" parts
>
> Best regards,
> John D.


It is not so much a "private" vs public stuff but it is a thing of
interfacing different objects of different types through a common interface.
 
Reply With Quote
 
ImpalerCore
Guest
Posts: n/a
 
      03-23-2010
On Mar 22, 2:57*pm, jacob navia <(E-Mail Removed)> wrote:
> ImpalerCore a écrit :
>
> > Personally I think implementing some public/private separation is
> > outside the scope of C. *Grafting this OO paradigm into C is purely
> > arbitrary at best, confusing and complex at worst. *C wants people to
> > get their hands dirty, and doesn't do a whole lot to protect them.

>
> Well, as you may have noticed, I proposed a common iterator object for
> iterating through ANY container in my library. Obviously that object
> can't be a SINGLE type, it must be several since it must have the specific
> knowledge of each container, AND it must offer a COMMON interface, so user
> code is independent of the container.
>
> It is not just "a matter of protecting people from themselves", it is
> just that is impossible to make a COMMON type for all container iterators
> if each iterator exposes its interface.
>
> The solution is then, to define a common interface with a few
> function pointers that is shared by all containers. User code uses that
> interface
>
> typedef struct _iterator {
> * * * * void (*Getnext)(structb_iterator *);
> * * * * // Some other public function pointers
> * * * * char private[]; // Document that this is a variable length structure
>
> } Iterator;
>
> In the file of the container implementation (say list.c) I
> define
>
> typedef struct tagListIterator {
> * * * * Iterator it;
> * * * * // Private fields follow
> * * * * List *list;
> * * * * unsigned timestamp;
> * * * * // etc
>
> } ListIterator;
>
> Now, I can define
>
> static void *GetNext(Iterator *it)
> {
> * * * * ListIterator *li = (ListIterator *)it;
>
> * * * * // And now I can use the private fields
> * * * * // in this implementation.
>
> }
>
> The advantage of this is that I can EXTEND a public structure with private
> parts, something similar to simple inheritance in C.


I can see your viewpoint better now, between this and your other
responses.

> > Again, you say a pure C solution is MUCH better, but I haven't seen a
> > really cool use-case that says "Yeah, I want to try it out!".

>
> When you write a library, it is very handy since it allows to present a common
> interface for a set of different objects


Fair enough, I'll wait to see how it all works when you release
something.

> > If I
> > wanted to make something private in C, I'd just give the "private"
> > members a hideously long name so that most people will just be annoyed/
> > bored to type it out and use the "public" parts

>
> > Best regards,
> > John D.

>
> It is not so much a "private" vs public stuff but it is a thing of
> interfacing different objects of different types through a common interface.


I suppose I took the private/public too literally. Probably a by-
product of learning C++ then coming to C I suppose.

Best regards,
John D.
 
Reply With Quote
 
Anand Hariharan
Guest
Posts: n/a
 
      03-23-2010
On Mar 21, 5:20*pm, jacob navia <(E-Mail Removed)> wrote:
> As you may have noticed, when I proposed the iterator object I splitted
> the object into a public part (the first 3 fields) an an undisclosed
> part specific to each iterator.
>
> This inheritance implementation looks like this:
>
> In the header file:
>
> typedef struct PublicStruct {
> * * * * // public fields
>
> } Public;
>
> In the implementation file (.c) we do:
>
> typedef struct Inherited {
> * * * * Public p;
> * * * * // follow the private fields
>
> } Private;
>
> The interface for all functions is just the public structure:
>
> void fn1(Public *);
> void fn2(Public *);
>
> The implementation of fn1 however, does this:
>
> void fn1(Public *p) {
> * * * * Private *pri = (Private *)p;
>
> * * * * // Work with the private struct.
> * * * * // It is assumed that the pointer
> * * * * // handed down is actually a private
> * * * * // pointer
>
> }
>
> Obviously this doesn't have any compiler support
> but works quite well in practice. You can add a
> "magic" number somewhere in the private struct
> in the debug version to catch mistakes when passing
> the structures.
>
> Obviously you aren't supposed to copy the public object since you do not
> know what is behind. A way to avoid that would be to add a VLA:
>
> typedef struct PublicStruct {
> * * * * // public fields
> * * * * // ...
> * * * * // private fields follow:
> * * * * char private[];
>
> } Public;
>
> YES I KNOW.
>
> C++/Java/C# do this MUCH better, but they have other drawbacks
> that make a pure C solution MUCH better. Thank you.



Am not sure if there is a question here. Also, you may already know
this, but you can control/restrict access by using the 'pimpl' idiom
(also known as the 'opaque structure'). Herb Sutter has written an
article or two regarding this (yes, they are C++ based, but the ideas
can be applied to C).

Basically you forward declare a structure that you want to be private
like so:

struct MyStructPrivates; /* forward declaration */

struct MyStruct
{
/* All your "public" stuff here */

struct MyStructPrivates *PtrToPrivate;
};

In the declaration of MyStructPrivates, you include the declaration of
MyStruct so you have access to the public parts of your struct.

The declaration of MyStructPrivates does not even have to be delivered
to the library user. Further, if anything changes in the
implementation of MyStructPrivates, your library users will remain
unaffected.

I haven't followed the other thread or read your iterator design, it
is possible I am way off-tangent here.

- Anand
 
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




Advertisments