
The C Object System (2010) - signa11
https://arxiv.org/abs/1003.2547
======
DonHopkins
This has been done before many times in many ways for many different purposes,
some worse than others, as object systems for C (Xtk intrinsics widgets, GTK's
GObjects), object systems written in C for other languages (ScriptX's "Objects
in C", TCL/Tk widgets, Lua objects), cross-language object systems (Microsoft
COM, IBM SOM, OpenDoc), distributed object proxy systems (CORBA, DCOM, DSOM),
and object oriented C language dialects (Objective C, C++, Java).

Not that it's not worth doing again for fun or to explore different techniques
and purposes. But the ones that are in use in the real world are incredibly
clumsy and complex, require a lot of boilerplate and yak shaving, and you have
to buy into a big toolchain and religion.

"The guy who invented the wheel was an idiot. The real genius was the guy who
invented the other three." -Sid Caesar

~~~
mpweiher
Marcel's corollary to Greenspun's tenth rule: any sufficiently large C/C++
contains an ad-hoc, informally-specified, bug-ridden, slow implementation of
most of Objective-C.

¯\\_(ツ)_/¯

------
sifoobar
Just say no, that path leads to madness. C is not the right language for fancy
abstractions, it will come back and bite your head off when you least expect
it. It can be done, but that doesn't mean worth doing. GObject suffers from
some of the same delusions.

The whole point of writing C is to keep it simple and only build exactly
what's needed. No other language I've tried comes close to supporting the same
level of custom fitting. This is also the reason it's potentially really fast;
more because it encourages simple, direct solutions than anything else.

Virtual dispatch is a function pointer, either embedded directly in the value
or together with others in a shared vtable. A type id may be added to the
vtable if needed. Avoid inheritance tricks, composition is mostly the right
answer in C. Downcasting is a solved [0] problem [1].

[0]
[https://gitlab.com/sifoo/snigl/blob/master/src/snigl/type.c#...](https://gitlab.com/sifoo/snigl/blob/master/src/snigl/type.c#L181)

[1]
[https://gitlab.com/sifoo/snigl/blob/master/src/snigl/util.h#...](https://gitlab.com/sifoo/snigl/blob/master/src/snigl/util.h#L17)

~~~
potiuper
[1] is #define[d] as sgl_baseof(type, field, ptr) that appears to used to
return a pointer to a "type", which is a value stored in memory at run-time,
of a field in an object (ptr)? I and many others would not consider a run-time
type system to be "the" solution to downcasting in C. Regarding the use of C
for "fancy abstractions" such as classes and objects, the derivatives of
Cfront (Corneau C/C++), which is an implementation of C++ using C, are not
just alive, but have been chosen to implement many production systems
([https://en.wikipedia.org/wiki/Edison_Design_Group](https://en.wikipedia.org/wiki/Edison_Design_Group))
used by millions today, although they too "inherit" the issues with the C
standard. It is true that the GObject system has many problems one of which is
the reference counting (sink/sunk) process as requiring a certain memory
(de)allocation mechanics as a requirement of the object system is not the most
applicable in certain situations.

~~~
sifoobar
The type in question is the containing C struct type. Think of sgl_baseof as
the opposite of offsetof. I didn't come up with it myself of course, it's
probably older than I am; I borrowed it from the Linux kernel. The other link
is an example of how it's used.

~~~
potiuper
sql_baseof as shown is defined in the header using offsetof. offsetof is an
implementation-specific macro. Whatever it does is specific to the compiler
that provides it. You cannot generalize from its definition for one or many
compilers to a language requirement.
[https://stackoverflow.com/questions/26906621/does-struct-
nam...](https://stackoverflow.com/questions/26906621/does-struct-name-null-b-
cause-undefined-behaviour-in-c11)

~~~
sifoobar
I fail to see your point here.

sgl_baseof uses offsetof with a valid struct type and a valid field name, so
where is the UB? Unless you feed it an invalid pointer, but then all bets are
off.

~~~
sifoobar
Sorry, still not getting it.

If an implementation provides offsetof and it doesn't work, that
implementation would go out of fashion in a heart beat.

Where is the practical use of this information?

How is this even an argument?

~~~
potiuper
The use of the Offsetof macro in a program will cause undefined behavior when
compiled with GCC or Clang and they are still "in fashion" as far as I am
aware. The practical use of this information is to prevent the occurrence of
undefined behavior by knowing not to use offsetof for example with GCC and
instead use __builtin_offsetof in the specific case of GCC. The argument
appears to be that you are claiming that what sgl_baseof does is not undefined
behavior and I am claiming that it is not possible to infer that without
specifying the implementation of the offsetof macro.

------
DonHopkins
Why not just write object oriented shell scripts and classes in the file
system? ;)

The patent's expired (I like to think of this as a Mercy Patent, that benefits
society by keeping people from doing this for 20 years):

Method for apparatus for implementing a class hierarchy of objects in a
hierarchical file system

[https://patents.google.com/patent/US5187786](https://patents.google.com/patent/US5187786)

Abstract

A method and apparatus for implementing a class hierarchy of objects in a
hierarchical file system is disclosed, which does not require the support of
additional file attributes by the hierarchical file system, and has particular
application to object oriented programming in window-based computer systems.
The class hierarchy comprises a root class, a plurality of classes and a
plurality of class instances. The root class is implemented with a hierarchy
of root class directory and root class files. Each class is implemented with a
hierarchy of class directories and class files comprising the class methods,
and the initial values of the class instance variables. Each class instance is
implemented with a hierarchy of class instance directory and class instance
files comprising the class instance variables. Each hierarchy of directories
and files also comprises a path file. The content of these path files are
logically related to each other, based on their class' relationships. By
controlling the invocation of class methods, using these path files,
inheritance is achieved. By accessing the class instance variables through the
class methods, data abstraction is also achieved. Additionally, the method and
apparatus also supports the pseudo class instance/class "Self" and "Super"
when invoking another class method by a class method.

------
armitron
This is cute, albeit a terrible idea in practice. It's also misleading to
compare it favorably to CLOS and come up with statements like "a framework
that brings C to the level of other high level programming languages and
beyond". It's a bad idea to examine CLOS in isolation and try to replicate its
features, without understanding - or ignoring - how it fits in with the rest
of Common Lisp and how the whole is greater than the sum of its parts. CLOS is
extremely powerful because there is tremendous synergy with the interactive,
image-based development style that CL is designed around.

You focus on CLOS in isolation and you not only end up missing the point
completely but also end up with a frankenstein monstrosity that can be very
destructive. This also reminds me of Alan Kay talking about how most OO
languages completely missed the point unlike Lisp that got it: Late binding.

~~~
appleflaxen
The Alan Kay talk sounds interesting; do you have a link to it?

~~~
armitron
It is his OOPSLA 97 keynote. I am sure you can find it online.

------
InGodsName
Is there anything similar for Go?

