Saturday, October 22, 2016

Node js C++ Addon Overload Resolution


Function overloads is not part of javascript as functions are objects inside object properties and object property names are unique.


I've attempted to add overload resolution on top of node js c++ addons for easily importing c++ libraries by having a middleware between v8 and the actual code executed.


Before you read on, make sure you understand Native Abstractions for Node.js (NAN) as it relies on it for some of its functionality and builds on top of it.

You can find the project and its tests at:
https://github.com/drorgl/node-overload-resolution

Structure

overload_resolution - the main class that registers and calls the overloaded functions, it provides a macro POLY_METHOD which is almost identical to NAN_METHOD for declaring functions and calling them after the correct overload has been determined.
by itself, the class does nothing, you will still have to register all the callbacks to overload_resolution::execute function for it to do anything:
Declare a callback:
namespace general_callback {
    std::shared_ptr<overload_resolution> overload;
    NAN_METHOD(tester_callback) {
        return overload->execute("current_namespace", info);
    }
}
in the init function, populate general_callback::overload with overload resolution instance:
general_callback::overload = overload;
and tell v8 you want to callback into tester_callback:
Nan::SetMethod(target, "overloaded_function", general_callback::tester_callback);
now the hook is ready to call overload_resolution::execute whenever overloaded_function is called, but we need to tell overload_resolution which function to call when an overload is matched:
constructor:
overload->addOverloadConstructor(
            "", 
                    "constructor_class_tester", 
                            { std::make_shared<overload_info>("a","Number",Nan::Undefined()) }, 
                                    New_number);
            ^ namespace or empty
                    ^ class name 
                            ^ array of parameter names, types and default values
                              note that Nan::Undefined is used as no default
                                    ^ callback POLY_METHOD
static:
overload->addStaticOverload(
            "", 
                    "constructor_class_tester", 
                            "static_function", 
                                    { std::make_shared<overload_info>("a","String",Nan::Undefined()) }, 
                                            static_function_static_string);
            ^ namespace or empty
                    ^ class name or function group name or empty
                            ^ function name
                                    ^ array of parameter names, types and default values
                                            ^ callback POLY_METHOD
member:
overload->addOverload(
            "", 
                    "constructor_class_tester", 
                            "member_function", 
                                    { std::make_shared<overload_info>("a","Map",Nan::Undefined()) }, 
                                            static_function_instance_map);
            ^ namespace or empty
                    ^ class name
                            ^ function name
                                    ^ array of parameter names, types and default values
                                            ^ callback POLY_METHOD

Issues

Currently the project is working but inefficient, it does a lot behind the scenes to determine which overload should be called and hopefully the performance issues will be resolved in the future, the slowest actions are around structs, which are very slow, they were intended as automatic object structure recognition and overload resolution accordingly.

Tests

Attempts were made to have as many tests as possible, at the moment of this update there are 2336 tests, all pass.

Future

If there will be future development, it should do the following:
  • performance analysis, solve the struct performance, check prototype inheritance performance and correctness, check big arrays performance.
  • implement macros
  • cleanup function registration
  • add logging and instrumentation

Monday, October 10, 2016

Lens Adventure

Recently I wanted to add an ultra wide angle lens to my photography skills, I've looked around and in my budget I've found only manual 2nd hand lenses, but then I've seen someone selling Canon 16-35 2.8 II in my budget, the problem was, it needed repair, the auto-focus and aperture didn't work and the lens would show ERR 1, but I thought about using it as a manual lens and I've decided to get into that adventure and see if I can fix it myself, not before looking all over eBay and aliexpress for replacement parts should I need it.

I've looked at some YouTube videos showing disassembly of that lens.

This one from TechnologyMafia shows a disassembly of this lens, I've learned a lot from it, though it didn't show some parts, like how to get the front element disassembled but it does show how the lens is constructed.



There's also this video by Jakob Dral, which shows a general workflow of how to order the disassembled parts so you can put it back together without "extra" screws, this guy has skills!



There's a full disassembly of the 24-105 by Francesco Capasso, which is pretty similar internally, this series of videos (1-5) is very good in terms of understanding how things fit together.



And I've found plenty of pictures for a different (yet somewhat similar) Canon 16-35 F4 by Roger Cicala from LensRentals.com, Thanks Roger for permission to use your pictures!

But in the end, no amount of videos are going to show how to fix your own lens, its only learning tools to make the experience more intuitive.

So after buying the lens and actually trying it for a minute or two, I had a feeling there's a problem in the bayonet, the errors and behavior of lens made me think its an electrical problem, so after opening the bayonet, I've checked the electrical connections and I've found out this ribbon is broken:


I didn't have too much patience to wait for a month, so I've attempted to repair it. In the "old days" we used to scrape some coating off the conductors and and solder them, but I remembered the coating would melt in the heat and I had an old broken 18-55 that I got as a "gift" so I've decided to try on it first. I've disassembled it and attempted to solder the ribbon, apparently things changed and 350C didn't melt the ribbon.

So, I've attempted to do that on the real thing and closed the lens and..... great! no more error 1!!


This is where the ribbon break. The one thing I didn't take a picture of... Thanks Roger for the image!

But the story doesn't end there. after playing with it for a few minutes I've discovered that it works great in aperture 2.8 but as soon as you change the aperture error 1 comes back.

I've looked up the prices for a new aperture diaphragm

(from here)

and a new ribbon cable for the diaphragm 

(from here)

and decided to try a disassembly practice to see if I can do it myself or give up and take it to a professional.



It took me a few hours, I wanted to do it right, disassemble it without using any force and take breaks every time my hands would start shaking or I lost the needed patience. 

Eventually I got to the focus element group and decided to stop since it looked like too many steps for my comfort zone which I pushed too far anyway.

I've decided to stop playing with it, clean all the elements thoroughly with lens cleaning pads and close it until the parts came in the mail, so I closed it up, connected all the ribbons and surprisingly it worked. so in the end it wasn't the diaphragm or the flexible cables, it was just a bad connection to the controller board. :-)


My take from this experience:
- Lens are exact science (obviously), so anything you take apart, no matter how simple it looks (like screws) probably have orientation and have been calibrated, these small plastic spacers most likely have orientation, mark it with a permanent marker on different angles (so you won't confuse between them) and its likely you'll be able to put it back together without ruining the calibration.
Mark the orientation! if you look closely, it has a thick side and thin side, so its actually a micro adjustment of the front element.

- Flexible ribbons are delicate, not feather delicate but enough to tear accidentally, before removing or replacing a part, look all around it that no ribbon has been caught between unintended parts.

- STOP as soon as you're starting to loose patience, next step will be a mistake.
- STOP as soon as your hands are starting to shake, next step will be a screw flying somewhere you didn't want.

I took breaks between sections, it helped me remember what goes where, I took plenty of photos of "before" so if I do forget, I'll have some kind of record of how things looked before.

At the moment the lens works, the focus is accurate but I didn't check it with a test pattern, there's a chance its not, in F5.6 its pretty sharp but in F2.8 the DOF is too shallow to be sure without a thorough test.

Experience rating, 9, it was fun, scary, interesting and I've learned a lot about canon 16-35, it has a solid build! let the photography experience begin! :-)

UPDATE Nov 3rd:
I've ordered a front barrel since the one this lens had was somewhat heavily used and dented, so here's how it looks now