Can a dynamic library reference Objective-C objects and still be unloaded? - objective-c

I know that, at least on OS X, due to the way classes are loaded by Apple's Objective-C runtime it is not possible to dynamically unload a dynamic library that contains the implementations of a loaded class. Does this hold true for a library that only knows about objects from referencing a header, but does not contain the method implementations of any class?
For clarity, I'd like to use Objective-C to write the dynamic library, but would load and unload functions with signatures like ResultObject* performActionOnObject(SomeObject* object).
Edit:
For more clarity, consider a function like
NSNumber* computeFactorial(NSNumber* operand){
NSUInteger n = [operand unsignedIntegerValue];
/// ... pure C loop omitted
return [NSNumber numberWithUnsignedInteger:n];
}
And assume when it is called an autorelease pool is active. Would that be okay to unload?

If the client references your class directly, it will result in a linker error if the class is not in a linked binary. You could load/unload classes at runtime, but you would need to look them up by their names (strings) to use them. You will also need to register the class(es) before you look them up by name.
You can pass C functions to runtime calls like class_addMethod and method_exchangeImplementations to extend/alter your ObjC class at runtime.
Googling "method swizzling" will lead you to examples.
So ultimately… "It depends on how you interface with the object".

Related

Bridge to objc, how can it knows arguments types?

I am writing a bridge from a language I am developing and ObjC.
There are several nice introspection C functions in the objective C runtime and I am able to retrieve arguments types for methods using method_getTypeEncoding.
The main problem is with object arguments which are returned as id (encoded as #) but what I would need is the real objc class name like NSString or NSNumber.
Is there a way to solve this issue without parsing the .h files?
Knowing something is an id allows you to know the size of the parameter, which is important when writing a scripting interface. Add another layer where you can dynamically verify assumptions using things like
[objectPassedIn isKindOfClass: [expectedType class]];
You want to be careful hardcoding things like, "Oh this is a string so look for __NSCFString" - because there's no way to know you'll get an instance of __NSCFString or another type. NSString is a class cluster - You could get any custom implementation back when using one.
The actual type of objects is not important to the Objective-C Runtime so you need to add your own layer. You might be able to get some useful info using Clang/llvm as a tool.

How does objective-c handle method resolution at run-time?

I've read here recently that an objective-c object is stored on the heap as a struct. The struct contains the objects iVars, inherited iVars, and the isa pointer.
I'm trying to figure out when I send a message to this object, how does the run-time figure out the code to run?
I know there is a class object for each class. Is this also stored on the heap?
I think the way it works is that the run-time gets the isa pointer from the struct, uses this to call the message on the class object. Is this correct?
In short, every Objective-C instance has a pointer to its class. The class contains an inventory of metadata that includes all the methods that the class implements. When a message is sent to an object -- when a method is called -- the runtime uses the pointer to the class to lookup the method by name and call it, if it can be found. If it isn't found, the runtime looks to the superclass (which is a part of each class's metadata) on up the inheritance chain to NSObject. If the method ultimately can't be found, the runtime goes through a series of last ditch efforts to see if their is an alternative handler and eventually raises an exception, if not.
If you want more detail than that, I wrote up a multipart tour of exactly how Objective-C method dispatch works. It is slightly out of date -- doesn't deal with ARC, tagged pointers or blocks-as-IMP -- but still fully applicable.
Yes, classes are stored in the heap, but generally not in malloc()d memory. Classes are generally loaded as read-only, shared, memory. That is, there will be only one copy of the NSString class in memory for all applications running on the system. You can dynamically create classes on the fly and these will be in the regular heap, but it is atypical.

Why do we have NSNumber and NSTemporaryNumber as two different classes?

I went through the source code of GNUStep's NSNumber's implementation to understand how does factory method implementation works there.
From there What I could understand was we have NSNumber with blank implementation for all initWithXYZ kind of methods. and NSTemporaryNumber was acting like an intermediate class in the hierarchy that implemented all the initWithXYZ methods where it actually created objects of specific types , autoreleased itself and returned the created object.
Also allocWithZone was overridden to avoid creation of NSNumber object and to create object of NSTemporaryNumber if it was so otherwise create objects of specific types.
What I didn't understand was, can't the same things be done by NSNumber itself ?
why give blank implementations at all , create the object of specific type and then autorelease self.
Also if we have implementations of createXYZ methods in NSNumber itself, why have initWithXYZ methods ?
If I have to implement a factory implementation for my project where say I have two mediaItems, video , audio and photo etc.
for which I have separate classes and corresponding enums which I pass to initWithMediaType who will create an object of correct child class, return it and destroy itself.
Have two classes like NSNumber and NSTemporaryNumber: say Media and TemporaryMedia, one with blank implementations other with implementations as mentioned above ?
Should I do something like this ?
Is this the way we have to implement Factory pattern in Objective C ?
My question might seem silly biut I come from a Java, C++ background where things looked different.
The purpose might be the same but I am finding it difficult to understand the way Objective C does it since it does not have abstract classes.
Link to the source:
http://www.koders.com/objectivec/fid46956186C20201706AFE1744AA7AFEEE09D1FE5A.aspx
The point is that NSNumber is a class cluster. The class you actually end up with may be an NSIntNumber, an NSFloatNumber or one of several others. They all respond to the same messages as NSNumber (and, usually in this pattern will be subclasses of it, but that isn't required) so it makes no real difference to the caller.
When you call alloc there's no way to know what sort of object to create, so a neutral type is created and returned instead. It substitutes appropriately upon receiving an appropriate init.
So this pattern is for the implementation of class clusters. You can ignore it if writing a class that provides only instances of itself.

Objective-C Find all init (constructor methods)

using the "Method * class_copyMethodList(Class cls, unsigned int *outCount)" function one can get a list of all methods that exist on an objective-C class.
I would like to know how to find which of these methods are constructors as I am writing an IOC container. I would like to determine the constructors and their parameter types.
I would like to know how to find which of these methods are
constructors as I am writing an IOC container. I would like to
determine the constructors and their parameter types.
In short, you can't. Or, at the least, you'll find that down this path lies madness.
First, Objective-C does not have constructors. It has initializers, sometimes many, and -- for a properly written class -- only one of which is the designated initializer. There is no way to identify the designated initializer at compile time or run time.
How do I use this with a Method * and no instantiated member of the
class?
You don't. First you allocate an instance of the class, then you initialize the instance.
Overall, this level of abstraction just isn't done in Objective-C outside of academic investigations. It can be done, but it is generally avoided because of the fragility of the resulting solution and the hairball of code-hell that is trying to dynamically support the underlying C ABI (go look at the source to libffi).
If you want to go down this path, then you are far better off either defining a custom abstract class that all of your containers will subclass that can provide the binding logic to the class behind it.
Or use protocols; i.e. a class could implement an IOCBean protocol and one method would be initIOCGoop that is the designated initializer goo.
Doing this generically for all classes is going to be rife with fragility, special cases, and will require a gigantic mess of code that will be difficult to maintain over time.
You can get the method signature by using the following method:
methodSignatureForSelector:
From the documentation:
An NSMethodSignature object records type information for the arguments and return value of a method. It is used to forward messages that the receiving object does not respond to—most notably in the case of distributed objects. You typically create an NSMethodSignature object using NSObject’s methodSignatureForSelector: instance method (on Mac OS X v10.5 and later you can also use signatureWithObjCTypes:). It is then used to create an NSInvocation object, which is passed as the argument to a forwardInvocation: message to send the invocation on to whatever other object can handle the message. In the default case, NSObject invokes doesNotRecognizeSelector:, which raises an exception. For distributed objects, the NSInvocation object is encoded using the information in the NSMethodSignature object and sent to the real object represented by the receiver of the message.

Why are Objective-C instance variables declared in an interface?

I'm just getting into Objective-C (Java is my primary OO language).
Defining an object's instance variables in the interface instead of the class seems strange. I'm used to an interface being a public API definition with nothing besides method signatures (not counting constants here).
Is there some reason that state is defined in an interface (even if it is private) and behaviour is defined in a class. It just seems odd that since objects are state+behavior that the definition would be split into two separate places.
Is it a design benefit is some way? A pain in the rear issue that you are just forced to deal with in Objective-C? A non-issue, just different? Any background on why it's done this way?
Or can you put object state in a class and I just haven't hit that part in my book yet?
UPDATE
The answer below was written before the language feature of declaring instance variables in the implementation was implemented. The premise of the question is now no longer valid. As FireLizzard says, nothing needs to go in the #interface that you don't want to be public.
It's a hangover from the fact that Objective-C originated as a fairly thin layer built on top of C. The C way is to define the interface to a module (do not confuse with a Java interface) in a header file and literally include it in each compilation unit. It's akin to automatically copy-pasting the declarations to the top of every compiled file. If that seems primitive, it is because it is, but C is a 40 year old language.
You have to define instance variables - even private ones - in the interface because Objective-C objects are implemented as C structs which are themselves just blocks of memory and named offsets within that block. The struct that represents an object of each class has to include space for the superclass instance variables so subclasses need to know at least the size of the C struct representing the superclass and also the public and protected instance variable offset. That, unfortunately, means that all the instance variables even private ones have to be exposed as part of the external interface.* C++ the other OO version of C suffers from the same problem for the same reasons.
It's a bit of a pain having to write down all the method signatures twice, but you get used to it.
*With the 64 bit runtime, you no longer need to declare the ivars for synthesized accessors in the #interface but since all methods are public, it still means exposing internal state to the outside World, althoug it does alleviate the fragile base class problem.
In Objective C interface does not refer to the instance at all
Brad Cox who designed Objective C decided that the equivalent of C declarations and definitions should be made explicit so each class has a #interface section telling what it looks like externally and an #implementation saying how it is implemented.
Java came along later and changed the object model so that there is only one definition of an object which pulled the #interface and #implementation together. The compiler (and runtime introspection) in effect construct the interface from the code.
The equivalent of an interface in Java is a Protocol in Objective C.
You just get used to it.