f



Embedding an Objective-C object in a C structure

Yup, i have a quite perver problem : i would like to embed an
Objective-C object within a C structure.

The reason is the following: i have an old code base that use a kind
of 'object oriented' style in C (stuff quite commons in the 80s and
90s), where an 'object', a kind of plugin for the application, is
defined in C by extending a struct, like in:

struct
{
   struct basic_object obj;
   ... new fields ..
}

I would like to migrate the code base toward Objective-C, but keeping
compatibility with the existing stuff.
I can of course install a second plugin definition API on the side of
the existing one, but what i really would like
is to make all the existing objects Objective-C objects, at least for
some basic functionality defined in some appropriately defined plugin
root class..

Essentially, i would like to do the equivalent of:

struct
{
   PlugInRootClass obj;
   ... new fields ...
}

Some trick is needed to reach this target, because the standard alloc/
init pattern does not help here.

I checked the apple run time function class_createInstance, that
allows to specify an extra size for the allocated
instance, that should provide what i am looking for.

Unfortunately, the code base need to run also on other gcc based
platforms (Linux, Windows/cygwin), and apparently the GNU objc runtime
corresponding function class_create_instance do not have this
possibility.

So, what else ? Creating the object and doing a quite direct memcpy
would works, for example ?

Any Idea ?

Thanks for reading,

Maurizio De Cecco

0
Maurizio
3/24/2010 5:07:51 PM
comp.lang.objective-c 1160 articles. 0 followers. Post Follow

8 Replies
950 Views

Similar Articles

[PageSpeed] 12

Hail

In article 
<fed2745a-a3ab-478d-8692-90ab1bb46ce9@b30g2000yqd.googlegroups.com>,
 Maurizio De Cecco <maurizio@dececco.name> wrote:

> Yup, i have a quite perver problem : i would like to embed an
> Objective-C object within a C structure.
> 
[snipt]
> 
> So, what else ? Creating the object and doing a quite direct memcpy
> would works, for example ?
> 
> Any Idea ?


Wouldn't you still need the ObjC runtime ?

I think it'd be easier to switch around to embed the C in an ObjC base, 
since that will work ab init.
0
William
3/24/2010 6:58:57 PM
On Mar 24, 10:07=A0am, Maurizio De Cecco <mauri...@dececco.name> wrote:
> Yup, i have a quite perver problem : i would like to embed an
> Objective-C object within a C structure.

If what you need is the DATA in the Object all you have to do is
extend the object to include a message that returns a struct with the
Data in it.

You might chsck out the @defs directive.

It's a compiler directive to get access to the internal memory layout
 of instances of a particular class.



Example:
[myClass.h]
@interface myClass : NSObject
{
  NSString *S;
  int      I;
  BOOL     B;
}
- init;
(NSString*) S;
(int)       I;
(Bool)      B;

@end


------------------------------------------------
[Myclass.m]
#import "myClass.h"
@implementation myClass

- init
{
  if (self =3D [super init])
  {
    S =3D [[NSString alloc] initWithCString:"A C String"];
    I =3D 123;
    B =3D YES;
  }
  return self;
}

(NSString*) S { return S; }

(int)       I { return I; }

(BOOL)      B { return B; }

@end

----------------------------------------
[main.m]

#import "myClass.h"

struct myClassStructure
{
  @defs(myClass);
} *myClassAsStruct;


int main ( int argc, char** argv, char** env)
{
   myClass* mc =3D [[myClass alloc] init];

    printf(" The value is %i\n", [mc I]);

    myClassAsStruct =3D (struct myClassStructure *) mc;

// access directly to data members
    mc->I =3D 23;

    mc->S =3D @"an NS String" ; // this might not work depends on
compiler internals

    mc->B =3D 0;   //0 is false, >0 is true. <0 ??


    printf(" The value is %i\n", mc->I);

return 0;
}

Should work for simple access to simple types. more complicated uses
become spaghetti,
and I would recommend you modify your classes to generate the data
structure you want.

perhaps use a category


@implementation myClass (Structable)

(Datastruct*) dataAsStruct{
   // code to generate a struct and fill it from copies
   // of data members inside the object
return mystruct;
}
@end

Just some ideas  off the cuff ...


0
spikeysnack
3/25/2010 10:44:07 PM
Thanks for the answers :->.

Actually, what i want to do is a little bit weird, i know, but there
are good reasons.

I think i failed to explain the main point: essentially, my
application (old code) have its own
object system coded in C. I want to *retrofit* this objects with an
Objective C infrastructure,
so that the objects written according to the current specifications
will be *magically* also
Objective C objects.

So, my need, very technical, is to embed an actual Object C object,
and a not a pointer, within a larger
C structure. In the meanwhile, i tryied the dirty memcpy trick, and it
works. Of course, it can be done
if the object life cycle is *not* handled by a garbage collector.

I have to leave for a meeting right now, but later i'll post some code
example to clarify my problem.

Maurizio
0
Maurizio
3/26/2010 8:55:15 AM
On 26 Mrz., 09:55, Maurizio De Cecco <mauri...@dececco.name> wrote:
> Thanks for the answers :->.
>
> Actually, what i want to do is a little bit weird, i know, but there
> are good reasons.
>
> I think i failed to explain the main point: essentially, my
> application (old code) have its own
> object system coded in C. I want to *retrofit* this objects with an
> Objective C infrastructure,
> so that the objects written according to the current specifications
> will be *magically* also
> Objective C objects.
>
> So, my need, very technical, is to embed an actual Object C object,
> and a not a pointer, within a larger
> C structure. In the meanwhile, i tryied the dirty memcpy trick, and it
> works. Of course, it can be done
> if the object life cycle is *not* handled by a garbage collector.
>
> I have to leave for a meeting right now, but later i'll post some code
> example to clarify my problem.
>
> Maurizio

Maybe you can do

struct {
  @defs(ObjcClass);
}

http://macdevelopertips.com/objective-c/objective-c-object-as-a-c-structure.html

-- hns

0
hns
3/26/2010 11:19:52 AM
OK, a bit more time to give some code example.

In the current system, we have a pseudo object oriented layer purely
in C.

To define an object class you define a structure like that:

typedef struct my_obj
{
  struct object_stub stub;
  int foo;
} my_obj_t;

And then you write some code like:

myclass = declare_class("MyClass", init_function, delete_function,
sizeof(my_obj_t));
declare_method(my_class, "setFoo", my_obj_set_foo);

Where, for example, my_obj_set_foo is C function defined like this:

void my_obj_set_foo(my_obj_t *this, int v)
{
  this->foo = v;
}

To send a message to the object you may write something like:

my_obj = new_object("MyClass");
send_message(my_obj, "setFoo", 10);

The struct object_stub declare all the data structure needed to the
runtime to handle the relationship
between the method and the class, and the method execution. If you
want, not very far from
what the Objetive C compiler and runtime do behind the curtains.  The
above is somehow a simplification of the actual
system, but close enough at least for what regards the problem in
discussion.

These kind of things were pretty common in the 80s, before a wider
adoption of real object oriented languages.
I have a code base of more than half a million lines of code using
this object system; the code roots
go back to the middle of the 80s.

I want to modernize the code base, and to introduce Objective-C as
implementation language.

One of the things i want to do, is to have objects with a double
nature, the original object system
and Objective C.

For writing new objects, an approach would be to define the object in
Objective C, and than to use
the @defs directive to obtain a C equivalent.

But my problem is with existing code (too much to imagine a
migration). In the above example, i want to make instances of the
MyClass
example visible also as Objective-C instances without changing the
source code of the object, essentially
retrofitting the existing object with a Objective-C nature;
i accept some limitation, for example that they are visible simply as
instances of the Object class or
of a to-be-implemented root class, common to all the objects. To keep
things simple to start with, lets say that
we are not interested to having the "setFoo" method callable from
ObjectiveC (but this is probably easy to
do using the dynamic mechanisms of Objective C).

The kind of solution i am thinking of is something of the kind:

Define the root class:

@interface MyRootClass : Object
{
  ... some basic stuff ...:
}

@end

Define the struct object_stub as being isomorph to MyRootClass:

struct object_stub
{
  @defs(MyRootClass);
}

And then keeping the rest of code unchanged.

That is fine, but how you create an instance of my_obj_t ?

Of course, [[MyRootClass alloc] init] would not work, because it would
not create the additional fields.

A standard C creation of the struct my_obj (malloc) would not work
either, because the
runtime structure of the ObjectiveC object would not be initialized.

Apparently, the class_createInstance function of the Apple ObjectiveC
runtime should
allow this:

 p = class_createInstance(objc_getClass("MyRootClass"),
sizeof(my_obj_t) - sizeof(struct object_stub));
 ... my_obj_t specific initialisations here ...

The object is allocated with declared extra space, that can be used by
the C object part.

I haven't found an equivalent on the GNU Objective C run time.
I tried a wild trick:

  obj = malloc(sizeof(my_obj_t));
  id = [MyRootClass alloc];
  memcpy(obj, id, sizeof(struct object_stub));
  id2 = (id) obj;
  [id2 init];

And than i can send an Objective C message to the object.

Of course, on the object lifecycle management side things may be a
little fuzzy after this :->

OK, that's all, thanks for reading,

Maurizio






0
Maurizio
3/26/2010 11:51:24 AM
[Man it sucksa when it sends your message when you hit the space bar
twice ..]

The evolution from C to Objective C begins as an analysis process of
grouping
functionalities together and defining classes and their methods as
self-sufficient
structures that create, destroy and alter themselves and provide
services to other objects.


First of all .. Objective-C is
A: slower than C ( a little)
B: More complicated than C ( a little)
C: An Object system built on top of C so all of C works with it.
D: The advantages of Objective-C over C are:
       its more dynamically typed
       its more organized from the source code side
       it has its own libraries that all work together in its own
language
       it allows you to modify and possibly override existing objects
and methods
       even if you don't have the source.
 E: writing class methods and C functions is the same or more amount
of work at the beginning.
    Only as a Class system matures does the organizational hierarchy
begin to pay dividends
    in coding ease, with subclassing and specialization.
F: Objc-runtime garbage collection is different (not better) than C
and different on different     platforms. C malloc and free works
transparently and the same on most all platforms.


Now to refactor existing C code "toward" objc code does not
automatically
gain you anything but coding experience hours. The challenge is to
create a new code base
that is superior to the old or that works with additional
functionality. Otherwise it just adds
a whole new branch of complexity to something already working ( more
things to break).

That said:
   Use objc to create factory and function objects that operate
simultaneously on
   both the old C objects and the new Objc objects. The Objc-runtime
can differentiate which
  method to use based upon the input types, so you write the same code
for both C and Objc     objects.

 Also you can create C-Style functions to operate on Objc objects.
Extern "C"{
/// c_style_func( ObjcObject* ){   }
}    can be used inline for these.


I have to say that the C++ template system makes these kinds of things
much easier, and
the objc++ compiler can be handy in this respect. C++ templates can
generate Objc objects
from C structs, along with Macros.

You must keep the C runtime of your program and the Objc runtime
separate; you should
be able to separately create and destroy the objects without seg
faults if you do.
Think of the system as a factory with two sides of the floor; the old
one and the new one.
Before an object from the C side can enter the Objc side, it needs to
be wrapped in an Objc Object and unwrapped before it is admitted back.
To destroy a C object it is sent back to the C side to be destroyed;an
Objc object can destroy itself. The key idea is that  the C system
never sees Objc Objects.

You don't need to rewrite all the C code, Objc Classes can call your C
functions and operate
on their instance variables directly that way.

It may be beneficial to generate a layer of C code functions above the
old struct/function system to make it easier to assimilate into a
class/method system.

Finally, you can stitch together functions and classes manually with
Selectors (SEL) and
implementation pointers (IMP).


SEL mySel = sel_getUid(name); // for Apple
SEL mySel = sel_get_any_uid(name); // for GNU Objective C

IMP myImp = [myObject methodFor:@selector(mySel)];
myImp(myObject,@selector(mySel));

Hope this gave you a little insight.
0
spikeysnack
3/27/2010 9:34:58 AM
On 27 mar, 11:34, spikeysnack <spikeysn...@gmail.com> wrote:
> [Man it sucksa when it sends your message when you hit the space bar
> twice ..]

>
> Hope this gave you a little insight.

Actually, not :->.

The problem is not on how to re-engineer an existing application
moving toward Objective C.
Your discussion of the subject is precise and interesting.

The problem is a lot more technical and specific, i haven't discussed
the general technical strategy behind
this move, that i am ready to discuss if you are interested, but it
would take quite some time; you can take
a look to www.jmax-phoenix.org for having an idea of the project.

The specific question can be re-formulated in: do the Gnu objective C
runtime provide anything that allow
to emulate the behaviour of the class_createInstance function in the
Apple runtime, specifically for what regards
the semantic of the second arguments ?

My best answer as of today is no, and it can be done either with some
horrible hack, or by taking the sources of the
runtime and writing the function myself, that is probably what i'll
do.

Thanks,
Maurizio


0
Maurizio
3/30/2010 8:22:25 AM
Hallo,

i found an answer to my problem, that i want to post if anyone ever
have the same problem.

As said, the objc_createInstance function in the Apple Objective-C run
time do not have an exact equivalent in the GNU Objective-C runtime,
but the NSAllocateObject function from the Foundation kit is
implemented in the Base library of GnuStep (and in the equivalent
of Cocotron, AFAIK), and have the required functionality (allocating
extra bytes to an object) so, a portable simple solution should be to
adopt the Foundation kit and use it on both Linux and MacOsX.

Thanks,
Maurizio
0
Maurizio
4/8/2010 1:17:39 PM
Reply: