Updates from May, 2012 Toggle Comment Threads | Keyboard Shortcuts

  • Andre Pareis 17:14 on 09.05.2012 Permalink | Reply
    Tags: ,   

    NSInvocation in Objective-C++ 

    UPDATE: This article was initially about some difficulties that I had calling some Objective-C++ code from C++ in a dynamic way using NSInvocation, which failed in the first place. I switched to directly calling the IMP pointer instead while passing C++ object pointers as arguments. Thanks to the comments that I received from bob, an obviously very experienced Objective-C++ developer, I could change the code and make it work also with NSInvocation.

    Here is a C++ class that represents the details of a notifier/observer association called Observation:

        class Observation: public Object {
        public:
    
            void setObjcObserver(NSObject *theObserver) { _nsObserver = theObserver; }
            void setObjcSlot(SEL theSlot) { _nsSlot = theSlot; }
                    
            void notify(bool complete);
            
            Observation() : _nsObserver(nil), _nsSlot(nil) {}
            
        private:
    
            Object *_notifier;
            NSObject *_nsObserver;
            SEL _nsSlot;
        };
    

    First Attempt Using NSInvocation Failed

        void Observation::notify(bool complete) {
    
            NSMethodSignature *aSignature = [[_nsObserver class]
                            instanceMethodSignatureForSelector:_nsSlot];
    
            assert(aSignature);
            assert([_nsObserver respondsToSelector:_nsSlot]);
    
            NSInvocation *anInvocation = [NSInvocation invocationWithMethodSignature:aSignature];
            [anInvocation setSelector:_nsSlot];
            [anInvocation setArgument:this atIndex:2];
            [anInvocation setArgument:&complete atIndex:3];
                
            [anInvocation invokeWithTarget:_nsObserver];
        }
    

    this code compiled fine but it crashed as soon as I tried to access members of the received Observation object in Objective-C.

    IMP Based Solution

    My approach to solve the issue is that I am directly calling the IMP of the method in the observer object. For this, I slightly change the C++ Observation model to cache the IMP pointer:

        class Observation: public Object {
        public:
    
            void setObjcObserver(NSObject *theObserver) { _nsObserver = theObserver; }
            void setObjcSlot(SEL theSlot) { _nsSlot = theSlot; }
                    
            void notify(bool complete);
            
            Observation() : _nsObserver(nil), _nsSlot(nil), _nsSlotImpl(nil) {}
            
        private:
    
            Object *_notifier;
            NSObject *_nsObserver;
            SEL _nsSlot;
    
            typedef void (*slotImpl_t)(__strong id, SEL, lang::Observation *, BOOL);
            
            // used to cache the IMP of the objcSlot
            slotImpl_t _nsSlotImpl;
    
        };
    

    Here, I simply add a typedef of the desired observer method signature called “slotImpl_t” and a member to cache the IMP function pointer. The cache would not be necessary but in my case the observer IMP will not change, so I cache it in order to save the look-up on frequent execution of the code. The notify() method now looks different:

        void Observation::notify(bool complete) {
            if(!_nsSlotImpl) {
                _nsSlotImpl = (slotImpl_t)[_nsObserver methodForSelector:_nsSlot];
                assert(_nsSlotImpl);
            }
            _nsSlotImpl(_nsObserver, _nsSlot, this, complete);
        }
    

    This is working like a charm now. The address of the Observation object at the receiving end is correct as it should be, even in case of multiple-inheritance combined with virtual inheritance.

    Correct Solution with NSInvocation

    It turned out that in my original solution using NSInvocation I did it wrong. NSInvocation needs the address of the this pointer and not the this pointer itself. To make it worse, when simply doing

            [anInvocation setArgument:&this atIndex:2];
    

    the compiler complains with the error:

    Address expression must be an lvalue or a function designator
    

    So, instead of &this it has to be an lvalue which essentially requires to copy the this pointer to a temporary variable, ‘temp’ in this case. Here is the complete and working code:

        void Observation::notify(bool complete) {
    
            NSMethodSignature *aSignature = [[_nsObserver class]
                            instanceMethodSignatureForSelector:_nsSlot];
    
            assert(aSignature);
            assert([_nsObserver respondsToSelector:_nsSlot]);
    
            NSInvocation *anInvocation = [NSInvocation invocationWithMethodSignature:aSignature];
            [anInvocation setSelector:_nsSlot];
            Observation *temp = this;
            [anInvocation setArgument:&temp atIndex:2];
            [anInvocation setArgument:&complete atIndex:3];
                
            [anInvocation invokeWithTarget:_nsObserver];
        }
    

    Conclusion

    There is expert knowlegde about Objective-C++ available on the planet. But it’s not easy to get access to it. Sometimes, it helps to blog about a problem and the solution will come and find you;) Again, bob, thank you very much

     
    • bob 21:32 on 04.06.2012 Permalink | Reply

      You are doing it wrong.
      It needs to be

      [anInvocation setArgument:&this atIndex:2];

      • Andre Pareis 21:52 on 04.06.2012 Permalink | Reply

        This one gives me an error: Address expression must be an lvalue or a function designator

    • bob 21:39 on 04.06.2012 Permalink | Reply

      Or if it is not possible to write “&this”, you can do

      Observation *temp = this;
      [anInvocation setArgument:&temp atIndex:2];

      • Andre Pareis 21:58 on 04.06.2012 Permalink | Reply

        I’m pretty sure that I tried “&this” before but, because of the compiler error above, I was mislead to think that taking the address of the this pointer was the wrong idea. Turns out it wasn’t. Using your modification the code is working as expected. Thank you very much for your fix, bob, I will adjust the blog post accordingly in order to not blame the language nor NSInvocation but just my stupidity;)

  • Andre Pareis 16:08 on 13.03.2012 Permalink | Reply
    Tags: ,   

    Multiple Inheritance in Objective-C / Core Data vs C++ 

    Multiple inheritance is hard. In fact it is so hard, that only very few programming languages support it. Objective-C is one for instance, where support for multiple inheritance is limited to the conformance to @protocols. Behavior can only be inherited from one single base class.

    If you need multiple inheritance in Objective-C you have several options to choose from. Most of the time when you are looking for answers to the question of how to do multiple inheritance in Objective-C the right way, you will be pointed into one of two directions: #1 don’t use it because it implies a flawed design. #2 do it using composition (via delegates).

    Option #1 I do not like at all. There are cases where MI is very well suited and only because Objective-C doesn’t support it doesn’t mean it is bad. It just means that the language designers considered it way too complicated to implement for the benefit of a few cases where it makes sense.

    For instance, my current use case with strong need for multiple inheritance support is the UML specification. UML makes heavy use of multiple inheritance and if you study the UML model you will find that the abstractions found in there make very well sense because they eliminate redundancy and the need to explain what’s going on. All those abstractions are basically orthogonal classifications which can be combined in a subclass to express things very precise and in a type-safe manner.

    So, if you are forced to deal with multiple inheritance in your program you can do so with option #2 in Objective-C. However, in my opinion, this has limitations. I will give you an example: Imagine a model like this:

    Let’s say we map this to the following physical implementation in Objective-C. Here, the greenish elements are Objective-C @protocol and the yellowish elements are Objective-C @class:

    It follows the often heard recommendation to map inheritance using composition. Here, the Class part of an AssociationClass is mapped to a delegate called “theClassImpl”, whereas the Association base class is mapped to plain Objective-C inheritance.

    Suppose now we want to map this structure to CoreData. We need to model NSManagedEntity with NSManagedProperty. CoreData does not work on top of @protocols but on actual @classes. Therefore, we have one physical implementation of the association between Class and Property (owningClass-properties).

    But here comes the big BUT: This can only work if we have full control over the OR mapping! CoreData on the other hand, does not rely on interfaces but on the actual implementations. That means, we must publish the otherwise internal composition mapping of theClassImpl to CoreData. If we then have a client of Class (for instance: Property::owningClass) then it will not be possible to downcast such a Class obtained from the persistence layer into an AssociationClass. Instead, it would be necessary to navigate backwards from the Class to the actual AssociationClass. But this kind of “alternative” cast can not be implemented transparently using Objective-C language constructs. An [aClass isKindOfClass:[AssociationClassImpl class]] would yield a technical “NO” and it’s not possible to extend the language to make it yield “YES”.

    Such an MI -> SI mapping scenario can only work if every consumer solely relies on the Interfaces only and makes no assumption about internal structures. This would imply that the ORM uses factories instead of instantiating from its meta information. In CoreData, this is not the case.

    This is why you can pretty much ignore the advice how to map multiple inheritance at the language level if you don’t also consider the APIs you’re dealing with because those APIs will render the easy sounding solution in the context of reality useless pretty quickly. In my case, I was forced to implement the model part of the system in C++ because C++ has awesomely good support for multiple inheritance. All problems related to the mapping of multiple inheritance to the microprocessor architecture had been solved by Bjarne Stroustrup in C++ since day 1. Read here why and how: http://drdobbs.com/184402074

    Here’s how the dreaded diamond from the example above would be implemented in C++:

    class Element {
    };
    
    class Association: public virtual Element {
    };
    
    class Class: public virtual Element {
    public:
        std::vector<class Property*> properties;
    };
    
    class Property: public Element {
    public:
        Class *owningClass;
    };
    
    class AssociationClass: public Association, public Class {
    };
    

    A straight 1:1 mapping of the concept to the language. Here, class “AssociationClass” would fully inherit the behavior of Class::properties without the need to implement something special. It just works. But, in comparison to Objective-C the C++ implementation lacks support for Core Data. But: so does multiple inheritance in Objective-C with CoreData! So no real difference here.

    Conclusion

    Multiple inheritance with CoreData is close to impossible except for very simple cases. With C++, besides all its ugliness and controversy, at least you get multiple inheritance in the language and usually in an implementation quality without the need to waste your time thinking around the whole concept.

     
  • Andre Pareis 23:14 on 09.06.2011 Permalink | Reply
    Tags: Social   

    How to Develop a Facebook App on Your Local Server using SSH 

    When you develop for facebook you usually run you app on your developer machine and connect a test app in Facebook with the local installation. Once finished, you put the final app onto some dedicated server and connect the real Facebook app to that. So setting up the local development environment usually includes some network setup, for instance as described here: http://www.insidefacebook.com/2007/07/16/how-to-local-facebook-app-development/ However, I find these router and network setup design troublesome and I also want something that is flexible, especially when I switch from desktop to mobile development.

    If you have access to a dedicated, root or v-server on the internet, you can achieve a very easy network setup using ssh port forwarding. You basically use the internet box as the target url for your Facebook app and forward some port from that internet port to your local test web server over the ssh tunnel. By doing so, you are totally mobile, you can open the port on the internet box from anywhere you want.

    So, let’s say you configured your facebook app “myapp” like this:

    You see in this example that facebook will tell your browser to load the iframe content from the URL http://my-domain.com:9090/ that is on port 9090. So you need to forward this port 9090 to your developer machine.

    In order to forward ports on public network interfaces you will mostly need to enable the “GatewayPorts” option in the ssh server of you internet box. This is a setting in the /etc/ssh/sshd_config (Debian):

    just add the following line to /etc/ssh/sshd_config:

    GatewayPorts yes

    and

    /etc/init.d/ssh restart

    Then you can start forwarding the port to your local machine. Just issue an

    ssh -R '*:9090:localhost:9000' me@my-domain.com

    It will look like you just only logged into the remote machine but in addition to that, a tunnel has been opened from port 9090 remote to port 9000 local. So if you have something listening on your local machine on port 9000, i.e., your development web server, than you can point the browser to your facebook app:

    http://apps.facebook.com/myapp

    and it will display the content as retrieved via the tunnel (9090) from your local machine (9000). As soon as you close the ssh connection, the tunnel will also be gone and you can then initiate the same ssh connection from you laptop if you are going outside.

    The biggest benefit of this solution is that you will never have to change IP addresses anywhere, not in the facebook app setting, not at dyndns etc. This is especially useful if your IP address changes frequently like on mobile internet.

    Pretty simple, and no need to configure multiple apps for multiple environments. Just move and reconnect via ssh. If you want, you can easily do the next step and put a web server like Apache or nginx on the internet box. From there you can reverse proxy from a certain virtual host (e.g., dev.my-domain.com) to your forwarded port on the same machine (9090). In a setup like this, you would not need to enable the “GatewayPorts” option in the ssh server, because then it would be sufficient to listen only on the local interface (127.0.0.1:9090). Such a setup would be a little closer to most production setups with load balancers and such.

     
  • Andre Pareis 21:47 on 26.04.2011 Permalink | Reply
    Tags: , ,   

    Beware of this: play framework’s cascaded save() only works on loaded collections 

    I am currently developing a web application using the really excellent play framework. If you are a web developer with some Java background I strongly encourage you to give it a try.

    However, play has taken a little different or let’s better call it an additional approach to control object synchronizations with the underlying database. Whereas JPA manages a loaded object graph and automatically persists any changes upon transaction completion, play has changed this behavior (“Explicit save”) to give the beginner more control over what is going on with the objects. This extension turns the implicit save mechanism into an explicit one where the developer is in control to call save() on the changed objects. This save() will in turn cascade (if for instance the CascadeType.ALL annotation option is present) to the reachable objects.

    This might in the first place seem clever because you get control back but I have mixed feelings about it because there are cases where it does just not work as easily as expected.

    As an example, imagine a 3-level parent-child object model.

    @Entity
    public class Item extends Model {
    
     @OneToMany(cascade = CascadeType.ALL, orphanRemoval=true, mappedBy="item")
           @OrderBy("createdAt")
     public List<Position> positions = new ArrayList<Position>();
    }
    
    @Entity
    public class Position extends Model {
    
     public Date createdAt = new Date();
     public int quantity;
    
     @ManyToOne public Item item;
    
     @OneToMany(cascade = CascadeType.ALL, orphanRemoval=true, mappedBy="position")
     @OrderBy("createdAt")
     public List<Order> orders = new ArrayList<Order>();
    }
    
    @Entity @Table(name="Ordr")
    public class Order extends Model { 
     public Date createdAt = new Date();
     public int quantity;
    
     @ManyToOne public Position position;
    }
    

    So far nothing complicated. But now imagine you are loading (for performance reasons) objects from the lowest level (Order) and manipulate the parent object (i.e., the Position).

    public void dostuff(Item item) {
    
     // load orders according to some important criteria
     List<Order> orders = Order.find("position.item = ? order by createdAt", item).fetch();
    
     // manipulate the parent of the order (the Position)
     Order order = extractImportantOne(orders);
     order.position.quantity += 200;
    
     item.save();
    }
    

    Intuitively I would assume that the manipulated Position object is updated in the database through the Item.positions cascade settings. But this is not the case here! The reason is that the collection Item.positions has not been populated from the database. Thus, play sees an unintialized PersistentCollection and will simply ignore to cascade.

    One solution to the problem would be to touch the cascading collection:

     item.positions.size();
     item.save();
    

    This will make sure the ‘positions’ collection will be considered during the following call to save(). With pure JPA on the other hand, such a call to do the trick would never be necessary and also the call to save() could be avoided, because JPA knows all loaded and changed objects and automatically updates the database.

    This is why I have very mixed feelings about play’s extended persistence API. It works well in simple cases but for more complex models it might be better to switch back to plain JPA mode.

     
c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r
Reply
e
Edit
o
Show/Hide comments
t
Go to top
l
Go to login
h
Show/Hide help
shift + esc
Cancel
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: