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





Saturday, September 24, 2016

Learning about V8 Objects

V8 Objects are documented thoroughly, however, reading documentation doesn't always help when you want to know how exactly it will manifest when calling a function with particular set of parameters in a particular state.

I've wrote this helper project to determine the exact values for each function call.

for example:

- calling a function without any parameters yields the following Nan::NAN_METHOD_ARGS_TYPE info

1:  {  
2:      "Length": 0,  
3:      "Callee": {  
4:          "IsUndefined": false,  
5:          "IsNull": false,  
6:          "IsTrue": false,  
7:          "IsFalse": false,  
8:          "IsName": false,  
9:          "IsString": false,  
10:          "IsSymbol": false,  
11:          "IsFunction": true,  
12:          "GetName": "test",  
13:          "GetInferredName": "",  
14:          "GetDebugName": "test",  
15:          "GetScriptLineNumber": -1,  
16:          "GetScriptColumnNumber": -1,  
17:          "IsBuiltin": true,  
18:          "ScriptId": 0,  
19:          "GetScriptOrigin": {  
20:              "Options": {  
21:                  "IsEmbedderDebugScript": false,  
22:                  "IsSharedCrossOrigin": false,  
23:                  "IsOpaque": false,  
24:                  "Flags": 0  
25:              }  
26:          },  
27:          "IsArray": false,  
28:          "IsObject": true,  
29:          "PropertyNames": [],  
30:          "GetConstructorName": "Function",  
31:          "InternalFieldCount": 0,  
32:          "HasNamedLookupInterceptor": false,  
33:          "HasIndexedLookupInterceptor": false,  
34:          "GetIdentityHash": 535707258,  
35:          "IsCallable": true,  
36:          "GetPrototype": {  
37:              "IsUndefined": false,  
38:              "IsNull": false,  
39:              "IsTrue": false,  
40:              "IsFalse": false,  
41:              "IsName": false,  
42:              "IsString": false,  
43:              "IsSymbol": false,  
44:              "IsFunction": true,  
45:              "IsArray": false,  
46:              "IsObject": true,  
47:              "IsBoolean": false,  
48:              "IsNumber": false,  
49:              "IsExternal": false,  
50:              "IsInt32": false,  
51:              "IsUint32": false,  
52:              "IsDate": false,  
53:              "IsArgumentsObject": false,  
54:              "IsBooleanObject": false,  
55:              "IsNumberObject": false,  
56:              "IsStringObject": false,  
57:              "IsSymbolObject": false,  
58:              "IsNativeError": false,  
59:              "IsRegExp": false,  
60:              "IsGeneratorFunction": false,  
61:              "IsGeneratorObject": false,  
62:              "IsPromise": false,  
63:              "IsMap": false,  
64:              "IsSet": false,  
65:              "IsMapIterator": false,  
66:              "IsSetIterator": false,  
67:              "IsWeakMap": false,  
68:              "IsWeakSet": false,  
69:              "IsArrayBuffer": false,  
70:              "IsArrayBufferView": false,  
71:              "IsTypedArray": false,  
72:              "IsUint8Array": false,  
73:              "IsUint8ClampedArray": false,  
74:              "IsInt8Array": false,  
75:              "IsUint16Array": false,  
76:              "IsInt16Array": false,  
77:              "IsUint32Array": false,  
78:              "IsInt32Array": false,  
79:              "IsFloat32Array": false,  
80:              "IsFloat64Array": false,  
81:              "IsDataView": false,  
82:              "IsSharedArrayBuffer": false,  
83:              "IsProxy": false,  
84:              "ToBoolean": true,  
85:              "ToNumber": null,  
86:              "ToString": "function () {}",  
87:              "ToDetailString": "function () {}",  
88:              "ToInteger": 0,  
89:              "ToUint32": 0,  
90:              "ToInt32": 0,  
91:              "BooleanValue": true,  
92:              "NumberValue": null,  
93:              "IntegerValue": 0,  
94:              "Uint32Value": 0,  
95:              "Int32Value": 0,  
96:              "PropertyNames": [],  
97:              "GetConstructorName": "Function",  
98:              "InternalFieldCount": 0,  
99:              "HasNamedLookupInterceptor": false,  
100:              "HasIndexedLookupInterceptor": false,  
101:              "GetIdentityHash": 2033009011,  
102:              "IsCallable": true  
103:          },  
104:          "IsBoolean": false,  
105:          "IsNumber": false,  
106:          "IsExternal": false,  
107:          "IsInt32": false,  
108:          "IsUint32": false,  
109:          "IsDate": false,  
110:          "IsArgumentsObject": false,  
111:          "IsBooleanObject": false,  
112:          "IsNumberObject": false,  
113:          "IsStringObject": false,  
114:          "IsSymbolObject": false,  
115:          "IsNativeError": false,  
116:          "IsRegExp": false,  
117:          "IsGeneratorFunction": false,  
118:          "IsGeneratorObject": false,  
119:          "IsPromise": false,  
120:          "IsMap": false,  
121:          "IsSet": false,  
122:          "IsMapIterator": false,  
123:          "IsSetIterator": false,  
124:          "IsWeakMap": false,  
125:          "IsWeakSet": false,  
126:          "IsArrayBuffer": false,  
127:          "IsArrayBufferView": false,  
128:          "IsTypedArray": false,  
129:          "IsUint8Array": false,  
130:          "IsUint8ClampedArray": false,  
131:          "IsInt8Array": false,  
132:          "IsUint16Array": false,  
133:          "IsInt16Array": false,  
134:          "IsUint32Array": false,  
135:          "IsInt32Array": false,  
136:          "IsFloat32Array": false,  
137:          "IsFloat64Array": false,  
138:          "IsDataView": false,  
139:          "IsSharedArrayBuffer": false,  
140:          "IsProxy": false,  
141:          "ToBoolean": true,  
142:          "ToNumber": null,  
143:          "ToString": "function test() { [native code] }",  
144:          "ToDetailString": "function test() { [native code] }",  
145:          "ToInteger": 0,  
146:          "ToUint32": 0,  
147:          "ToInt32": 0,  
148:          "BooleanValue": true,  
149:          "NumberValue": null,  
150:          "IntegerValue": 0,  
151:          "Uint32Value": 0,  
152:          "Int32Value": 0  
153:      },  
154:      "IsConstructCall": false,  
155:      "This": {  
156:          "IsUndefined": false,  
157:          "IsNull": false,  
158:          "IsTrue": false,  
159:          "IsFalse": false,  
160:          "IsName": false,  
161:          "IsString": false,  
162:          "IsSymbol": false,  
163:          "IsFunction": false,  
164:          "IsArray": false,  
165:          "IsObject": true,  
166:          "PropertyNames": [],  
167:          "GetConstructorName": "Object",  
168:          "InternalFieldCount": 0,  
169:          "HasNamedLookupInterceptor": false,  
170:          "HasIndexedLookupInterceptor": false,  
171:          "GetIdentityHash": 716126579,  
172:          "IsCallable": false,  
173:          "GetPrototype": {  
174:              "IsUndefined": false,  
175:              "IsNull": false,  
176:              "IsTrue": false,  
177:              "IsFalse": false,  
178:              "IsName": false,  
179:              "IsString": false,  
180:              "IsSymbol": false,  
181:              "IsFunction": false,  
182:              "IsArray": false,  
183:              "IsObject": true,  
184:              "IsBoolean": false,  
185:              "IsNumber": false,  
186:              "IsExternal": false,  
187:              "IsInt32": false,  
188:              "IsUint32": false,  
189:              "IsDate": false,  
190:              "IsArgumentsObject": false,  
191:              "IsBooleanObject": false,  
192:              "IsNumberObject": false,  
193:              "IsStringObject": false,  
194:              "IsSymbolObject": false,  
195:              "IsNativeError": false,  
196:              "IsRegExp": false,  
197:              "IsGeneratorFunction": false,  
198:              "IsGeneratorObject": false,  
199:              "IsPromise": false,  
200:              "IsMap": false,  
201:              "IsSet": false,  
202:              "IsMapIterator": false,  
203:              "IsSetIterator": false,  
204:              "IsWeakMap": false,  
205:              "IsWeakSet": false,  
206:              "IsArrayBuffer": false,  
207:              "IsArrayBufferView": false,  
208:              "IsTypedArray": false,  
209:              "IsUint8Array": false,  
210:              "IsUint8ClampedArray": false,  
211:              "IsInt8Array": false,  
212:              "IsUint16Array": false,  
213:              "IsInt16Array": false,  
214:              "IsUint32Array": false,  
215:              "IsInt32Array": false,  
216:              "IsFloat32Array": false,  
217:              "IsFloat64Array": false,  
218:              "IsDataView": false,  
219:              "IsSharedArrayBuffer": false,  
220:              "IsProxy": false,  
221:              "ToBoolean": true,  
222:              "ToNumber": null,  
223:              "ToString": "[object Object]",  
224:              "ToDetailString": "#<Object>",  
225:              "ToObject": {},  
226:              "ToInteger": 0,  
227:              "ToUint32": 0,  
228:              "ToInt32": 0,  
229:              "BooleanValue": true,  
230:              "NumberValue": null,  
231:              "IntegerValue": 0,  
232:              "Uint32Value": 0,  
233:              "Int32Value": 0,  
234:              "PropertyNames": [],  
235:              "GetConstructorName": "Object",  
236:              "InternalFieldCount": 0,  
237:              "HasNamedLookupInterceptor": false,  
238:              "HasIndexedLookupInterceptor": false,  
239:              "GetIdentityHash": 1536014436,  
240:              "IsCallable": false  
241:          },  
242:          "IsBoolean": false,  
243:          "IsNumber": false,  
244:          "IsExternal": false,  
245:          "IsInt32": false,  
246:          "IsUint32": false,  
247:          "IsDate": false,  
248:          "IsArgumentsObject": false,  
249:          "IsBooleanObject": false,  
250:          "IsNumberObject": false,  
251:          "IsStringObject": false,  
252:          "IsSymbolObject": false,  
253:          "IsNativeError": false,  
254:          "IsRegExp": false,  
255:          "IsGeneratorFunction": false,  
256:          "IsGeneratorObject": false,  
257:          "IsPromise": false,  
258:          "IsMap": false,  
259:          "IsSet": false,  
260:          "IsMapIterator": false,  
261:          "IsSetIterator": false,  
262:          "IsWeakMap": false,  
263:          "IsWeakSet": false,  
264:          "IsArrayBuffer": false,  
265:          "IsArrayBufferView": false,  
266:          "IsTypedArray": false,  
267:          "IsUint8Array": false,  
268:          "IsUint8ClampedArray": false,  
269:          "IsInt8Array": false,  
270:          "IsUint16Array": false,  
271:          "IsInt16Array": false,  
272:          "IsUint32Array": false,  
273:          "IsInt32Array": false,  
274:          "IsFloat32Array": false,  
275:          "IsFloat64Array": false,  
276:          "IsDataView": false,  
277:          "IsSharedArrayBuffer": false,  
278:          "IsProxy": false,  
279:          "ToBoolean": true,  
280:          "ToNumber": null,  
281:          "ToString": "[object Object]",  
282:          "ToDetailString": "#<Object>",  
283:          "ToObject": {},  
284:          "ToInteger": 0,  
285:          "ToUint32": 0,  
286:          "ToInt32": 0,  
287:          "BooleanValue": true,  
288:          "NumberValue": null,  
289:          "IntegerValue": 0,  
290:          "Uint32Value": 0,  
291:          "Int32Value": 0  
292:      },  
293:      "Info": []  
294:  }  


- calling a member function (prototype) yields:

1:   {  
2:      "Length": 0,  
3:      "Callee": {  
4:          "IsUndefined": false,  
5:          "IsNull": false,  
6:          "IsTrue": false,  
7:          "IsFalse": false,  
8:          "IsName": false,  
9:          "IsString": false,  
10:          "IsSymbol": false,  
11:          "IsFunction": true,  
12:          "GetName": "test_member_function",  
13:          "GetInferredName": "",  
14:          "GetDebugName": "test_member_function",  
15:          "GetScriptLineNumber": -1,  
16:          "GetScriptColumnNumber": -1,  
17:          "IsBuiltin": true,  
18:          "ScriptId": 0,  
19:          "GetScriptOrigin": {  
20:              "Options": {  
21:                  "IsEmbedderDebugScript": false,  
22:                  "IsSharedCrossOrigin": false,  
23:                  "IsOpaque": false,  
24:                  "Flags": 0  
25:              }  
26:          },  
27:          "IsArray": false,  
28:          "IsObject": true,  
29:          "PropertyNames": [],  
30:          "GetConstructorName": "Function",  
31:          "InternalFieldCount": 0,  
32:          "HasNamedLookupInterceptor": false,  
33:          "HasIndexedLookupInterceptor": false,  
34:          "GetIdentityHash": 1864397598,  
35:          "IsCallable": true,  
36:          "GetPrototype": {  
37:              "IsUndefined": false,  
38:              "IsNull": false,  
39:              "IsTrue": false,  
40:              "IsFalse": false,  
41:              "IsName": false,  
42:              "IsString": false,  
43:              "IsSymbol": false,  
44:              "IsFunction": true,  
45:              "IsArray": false,  
46:              "IsObject": true,  
47:              "IsBoolean": false,  
48:              "IsNumber": false,  
49:              "IsExternal": false,  
50:              "IsInt32": false,  
51:              "IsUint32": false,  
52:              "IsDate": false,  
53:              "IsArgumentsObject": false,  
54:              "IsBooleanObject": false,  
55:              "IsNumberObject": false,  
56:              "IsStringObject": false,  
57:              "IsSymbolObject": false,  
58:              "IsNativeError": false,  
59:              "IsRegExp": false,  
60:              "IsGeneratorFunction": false,  
61:              "IsGeneratorObject": false,  
62:              "IsPromise": false,  
63:              "IsMap": false,  
64:              "IsSet": false,  
65:              "IsMapIterator": false,  
66:              "IsSetIterator": false,  
67:              "IsWeakMap": false,  
68:              "IsWeakSet": false,  
69:              "IsArrayBuffer": false,  
70:              "IsArrayBufferView": false,  
71:              "IsTypedArray": false,  
72:              "IsUint8Array": false,  
73:              "IsUint8ClampedArray": false,  
74:              "IsInt8Array": false,  
75:              "IsUint16Array": false,  
76:              "IsInt16Array": false,  
77:              "IsUint32Array": false,  
78:              "IsInt32Array": false,  
79:              "IsFloat32Array": false,  
80:              "IsFloat64Array": false,  
81:              "IsDataView": false,  
82:              "IsSharedArrayBuffer": false,  
83:              "IsProxy": false,  
84:              "ToBoolean": true,  
85:              "ToNumber": null,  
86:              "ToString": "function () {}",  
87:              "ToDetailString": "function () {}",  
88:              "ToInteger": 0,  
89:              "ToUint32": 0,  
90:              "ToInt32": 0,  
91:              "BooleanValue": true,  
92:              "NumberValue": null,  
93:              "IntegerValue": 0,  
94:              "Uint32Value": 0,  
95:              "Int32Value": 0,  
96:              "PropertyNames": [],  
97:              "GetConstructorName": "Function",  
98:              "InternalFieldCount": 0,  
99:              "HasNamedLookupInterceptor": false,  
100:              "HasIndexedLookupInterceptor": false,  
101:              "GetIdentityHash": 1117981863,  
102:              "IsCallable": true  
103:          },  
104:          "IsBoolean": false,  
105:          "IsNumber": false,  
106:          "IsExternal": false,  
107:          "IsInt32": false,  
108:          "IsUint32": false,  
109:          "IsDate": false,  
110:          "IsArgumentsObject": false,  
111:          "IsBooleanObject": false,  
112:          "IsNumberObject": false,  
113:          "IsStringObject": false,  
114:          "IsSymbolObject": false,  
115:          "IsNativeError": false,  
116:          "IsRegExp": false,  
117:          "IsGeneratorFunction": false,  
118:          "IsGeneratorObject": false,  
119:          "IsPromise": false,  
120:          "IsMap": false,  
121:          "IsSet": false,  
122:          "IsMapIterator": false,  
123:          "IsSetIterator": false,  
124:          "IsWeakMap": false,  
125:          "IsWeakSet": false,  
126:          "IsArrayBuffer": false,  
127:          "IsArrayBufferView": false,  
128:          "IsTypedArray": false,  
129:          "IsUint8Array": false,  
130:          "IsUint8ClampedArray": false,  
131:          "IsInt8Array": false,  
132:          "IsUint16Array": false,  
133:          "IsInt16Array": false,  
134:          "IsUint32Array": false,  
135:          "IsInt32Array": false,  
136:          "IsFloat32Array": false,  
137:          "IsFloat64Array": false,  
138:          "IsDataView": false,  
139:          "IsSharedArrayBuffer": false,  
140:          "IsProxy": false,  
141:          "ToBoolean": true,  
142:          "ToNumber": null,  
143:          "ToString": "function test_member_function() { [native code] }",  
144:          "ToDetailString": "function test_member_function() { [native code] }",  
145:          "ToInteger": 0,  
146:          "ToUint32": 0,  
147:          "ToInt32": 0,  
148:          "BooleanValue": true,  
149:          "NumberValue": null,  
150:          "IntegerValue": 0,  
151:          "Uint32Value": 0,  
152:          "Int32Value": 0  
153:      },  
154:      "IsConstructCall": false,  
155:      "This": {  
156:          "IsUndefined": false,  
157:          "IsNull": false,  
158:          "IsTrue": false,  
159:          "IsFalse": false,  
160:          "IsName": false,  
161:          "IsString": false,  
162:          "IsSymbol": false,  
163:          "IsFunction": false,  
164:          "IsArray": false,  
165:          "IsObject": true,  
166:          "PropertyNames": [],  
167:          "GetConstructorName": "base_class",  
168:          "InternalFieldCount": 1,  
169:          "HasNamedLookupInterceptor": false,  
170:          "HasIndexedLookupInterceptor": false,  
171:          "GetIdentityHash": 1554520219,  
172:          "IsCallable": false,  
173:          "GetPrototype": {  
174:              "IsUndefined": false,  
175:              "IsNull": false,  
176:              "IsTrue": false,  
177:              "IsFalse": false,  
178:              "IsName": false,  
179:              "IsString": false,  
180:              "IsSymbol": false,  
181:              "IsFunction": false,  
182:              "IsArray": false,  
183:              "IsObject": true,  
184:              "IsBoolean": false,  
185:              "IsNumber": false,  
186:              "IsExternal": false,  
187:              "IsInt32": false,  
188:              "IsUint32": false,  
189:              "IsDate": false,  
190:              "IsArgumentsObject": false,  
191:              "IsBooleanObject": false,  
192:              "IsNumberObject": false,  
193:              "IsStringObject": false,  
194:              "IsSymbolObject": false,  
195:              "IsNativeError": false,  
196:              "IsRegExp": false,  
197:              "IsGeneratorFunction": false,  
198:              "IsGeneratorObject": false,  
199:              "IsPromise": false,  
200:              "IsMap": false,  
201:              "IsSet": false,  
202:              "IsMapIterator": false,  
203:              "IsSetIterator": false,  
204:              "IsWeakMap": false,  
205:              "IsWeakSet": false,  
206:              "IsArrayBuffer": false,  
207:              "IsArrayBufferView": false,  
208:              "IsTypedArray": false,  
209:              "IsUint8Array": false,  
210:              "IsUint8ClampedArray": false,  
211:              "IsInt8Array": false,  
212:              "IsUint16Array": false,  
213:              "IsInt16Array": false,  
214:              "IsUint32Array": false,  
215:              "IsInt32Array": false,  
216:              "IsFloat32Array": false,  
217:              "IsFloat64Array": false,  
218:              "IsDataView": false,  
219:              "IsSharedArrayBuffer": false,  
220:              "IsProxy": false,  
221:              "ToBoolean": true,  
222:              "ToNumber": null,  
223:              "ToString": "[object Object]",  
224:              "ToDetailString": "#<base_class>",  
225:              "ToObject": {},  
226:              "ToInteger": 0,  
227:              "ToUint32": 0,  
228:              "ToInt32": 0,  
229:              "BooleanValue": true,  
230:              "NumberValue": null,  
231:              "IntegerValue": 0,  
232:              "Uint32Value": 0,  
233:              "Int32Value": 0,  
234:              "PropertyNames": [],  
235:              "GetConstructorName": "Object",  
236:              "InternalFieldCount": 0,  
237:              "HasNamedLookupInterceptor": false,  
238:              "HasIndexedLookupInterceptor": false,  
239:              "GetIdentityHash": 1008670604,  
240:              "IsCallable": false  
241:          },  
242:          "IsBoolean": false,  
243:          "IsNumber": false,  
244:          "IsExternal": false,  
245:          "IsInt32": false,  
246:          "IsUint32": false,  
247:          "IsDate": false,  
248:          "IsArgumentsObject": false,  
249:          "IsBooleanObject": false,  
250:          "IsNumberObject": false,  
251:          "IsStringObject": false,  
252:          "IsSymbolObject": false,  
253:          "IsNativeError": false,  
254:          "IsRegExp": false,  
255:          "IsGeneratorFunction": false,  
256:          "IsGeneratorObject": false,  
257:          "IsPromise": false,  
258:          "IsMap": false,  
259:          "IsSet": false,  
260:          "IsMapIterator": false,  
261:          "IsSetIterator": false,  
262:          "IsWeakMap": false,  
263:          "IsWeakSet": false,  
264:          "IsArrayBuffer": false,  
265:          "IsArrayBufferView": false,  
266:          "IsTypedArray": false,  
267:          "IsUint8Array": false,  
268:          "IsUint8ClampedArray": false,  
269:          "IsInt8Array": false,  
270:          "IsUint16Array": false,  
271:          "IsInt16Array": false,  
272:          "IsUint32Array": false,  
273:          "IsInt32Array": false,  
274:          "IsFloat32Array": false,  
275:          "IsFloat64Array": false,  
276:          "IsDataView": false,  
277:          "IsSharedArrayBuffer": false,  
278:          "IsProxy": false,  
279:          "ToBoolean": true,  
280:          "ToNumber": null,  
281:          "ToString": "[object base_class]",  
282:          "ToDetailString": "#<base_class>",  
283:          "ToObject": {},  
284:          "ToInteger": 0,  
285:          "ToUint32": 0,  
286:          "ToInt32": 0,  
287:          "BooleanValue": true,  
288:          "NumberValue": null,  
289:          "IntegerValue": 0,  
290:          "Uint32Value": 0,  
291:          "Int32Value": 0  
292:      },  
293:      "Info": []  
294:  }  


- calling a "static" function yields:

1:  {  
2:      "Length": 0,  
3:      "Callee": {  
4:          "IsUndefined": false,  
5:          "IsNull": false,  
6:          "IsTrue": false,  
7:          "IsFalse": false,  
8:          "IsName": false,  
9:          "IsString": false,  
10:          "IsSymbol": false,  
11:          "IsFunction": true,  
12:          "GetName": "test_static_function",  
13:          "GetInferredName": "",  
14:          "GetDebugName": "test_static_function",  
15:          "GetScriptLineNumber": -1,  
16:          "GetScriptColumnNumber": -1,  
17:          "IsBuiltin": true,  
18:          "ScriptId": 0,  
19:          "GetScriptOrigin": {  
20:              "Options": {  
21:                  "IsEmbedderDebugScript": false,  
22:                  "IsSharedCrossOrigin": false,  
23:                  "IsOpaque": false,  
24:                  "Flags": 0  
25:              }  
26:          },  
27:          "IsArray": false,  
28:          "IsObject": true,  
29:          "PropertyNames": [],  
30:          "GetConstructorName": "Function",  
31:          "InternalFieldCount": 0,  
32:          "HasNamedLookupInterceptor": false,  
33:          "HasIndexedLookupInterceptor": false,  
34:          "GetIdentityHash": 994160730,  
35:          "IsCallable": true,  
36:          "GetPrototype": {  
37:              "IsUndefined": false,  
38:              "IsNull": false,  
39:              "IsTrue": false,  
40:              "IsFalse": false,  
41:              "IsName": false,  
42:              "IsString": false,  
43:              "IsSymbol": false,  
44:              "IsFunction": true,  
45:              "IsArray": false,  
46:              "IsObject": true,  
47:              "IsBoolean": false,  
48:              "IsNumber": false,  
49:              "IsExternal": false,  
50:              "IsInt32": false,  
51:              "IsUint32": false,  
52:              "IsDate": false,  
53:              "IsArgumentsObject": false,  
54:              "IsBooleanObject": false,  
55:              "IsNumberObject": false,  
56:              "IsStringObject": false,  
57:              "IsSymbolObject": false,  
58:              "IsNativeError": false,  
59:              "IsRegExp": false,  
60:              "IsGeneratorFunction": false,  
61:              "IsGeneratorObject": false,  
62:              "IsPromise": false,  
63:              "IsMap": false,  
64:              "IsSet": false,  
65:              "IsMapIterator": false,  
66:              "IsSetIterator": false,  
67:              "IsWeakMap": false,  
68:              "IsWeakSet": false,  
69:              "IsArrayBuffer": false,  
70:              "IsArrayBufferView": false,  
71:              "IsTypedArray": false,  
72:              "IsUint8Array": false,  
73:              "IsUint8ClampedArray": false,  
74:              "IsInt8Array": false,  
75:              "IsUint16Array": false,  
76:              "IsInt16Array": false,  
77:              "IsUint32Array": false,  
78:              "IsInt32Array": false,  
79:              "IsFloat32Array": false,  
80:              "IsFloat64Array": false,  
81:              "IsDataView": false,  
82:              "IsSharedArrayBuffer": false,  
83:              "IsProxy": false,  
84:              "ToBoolean": true,  
85:              "ToNumber": null,  
86:              "ToString": "function () {}",  
87:              "ToDetailString": "function () {}",  
88:              "ToInteger": 0,  
89:              "ToUint32": 0,  
90:              "ToInt32": 0,  
91:              "BooleanValue": true,  
92:              "NumberValue": null,  
93:              "IntegerValue": 0,  
94:              "Uint32Value": 0,  
95:              "Int32Value": 0,  
96:              "PropertyNames": [],  
97:              "GetConstructorName": "Function",  
98:              "InternalFieldCount": 0,  
99:              "HasNamedLookupInterceptor": false,  
100:              "HasIndexedLookupInterceptor": false,  
101:              "GetIdentityHash": 1329899702,  
102:              "IsCallable": true  
103:          },  
104:          "IsBoolean": false,  
105:          "IsNumber": false,  
106:          "IsExternal": false,  
107:          "IsInt32": false,  
108:          "IsUint32": false,  
109:          "IsDate": false,  
110:          "IsArgumentsObject": false,  
111:          "IsBooleanObject": false,  
112:          "IsNumberObject": false,  
113:          "IsStringObject": false,  
114:          "IsSymbolObject": false,  
115:          "IsNativeError": false,  
116:          "IsRegExp": false,  
117:          "IsGeneratorFunction": false,  
118:          "IsGeneratorObject": false,  
119:          "IsPromise": false,  
120:          "IsMap": false,  
121:          "IsSet": false,  
122:          "IsMapIterator": false,  
123:          "IsSetIterator": false,  
124:          "IsWeakMap": false,  
125:          "IsWeakSet": false,  
126:          "IsArrayBuffer": false,  
127:          "IsArrayBufferView": false,  
128:          "IsTypedArray": false,  
129:          "IsUint8Array": false,  
130:          "IsUint8ClampedArray": false,  
131:          "IsInt8Array": false,  
132:          "IsUint16Array": false,  
133:          "IsInt16Array": false,  
134:          "IsUint32Array": false,  
135:          "IsInt32Array": false,  
136:          "IsFloat32Array": false,  
137:          "IsFloat64Array": false,  
138:          "IsDataView": false,  
139:          "IsSharedArrayBuffer": false,  
140:          "IsProxy": false,  
141:          "ToBoolean": true,  
142:          "ToNumber": null,  
143:          "ToString": "function test_static_function() { [native code] }",  
144:          "ToDetailString": "function test_static_function() { [native code] }",  
145:          "ToInteger": 0,  
146:          "ToUint32": 0,  
147:          "ToInt32": 0,  
148:          "BooleanValue": true,  
149:          "NumberValue": null,  
150:          "IntegerValue": 0,  
151:          "Uint32Value": 0,  
152:          "Int32Value": 0  
153:      },  
154:      "IsConstructCall": false,  
155:      "This": {  
156:          "IsUndefined": false,  
157:          "IsNull": false,  
158:          "IsTrue": false,  
159:          "IsFalse": false,  
160:          "IsName": false,  
161:          "IsString": false,  
162:          "IsSymbol": false,  
163:          "IsFunction": true,  
164:          "GetName": "base_class",  
165:          "GetInferredName": "",  
166:          "GetDebugName": "base_class",  
167:          "GetScriptLineNumber": -1,  
168:          "GetScriptColumnNumber": -1,  
169:          "IsBuiltin": true,  
170:          "ScriptId": 0,  
171:          "GetScriptOrigin": {  
172:              "Options": {  
173:                  "IsEmbedderDebugScript": false,  
174:                  "IsSharedCrossOrigin": false,  
175:                  "IsOpaque": false,  
176:                  "Flags": 0  
177:              }  
178:          },  
179:          "IsArray": false,  
180:          "IsObject": true,  
181:          "PropertyNames": [],  
182:          "GetConstructorName": "Function",  
183:          "InternalFieldCount": 0,  
184:          "HasNamedLookupInterceptor": false,  
185:          "HasIndexedLookupInterceptor": false,  
186:          "GetIdentityHash": 612374797,  
187:          "IsCallable": true,  
188:          "GetPrototype": {  
189:              "IsUndefined": false,  
190:              "IsNull": false,  
191:              "IsTrue": false,  
192:              "IsFalse": false,  
193:              "IsName": false,  
194:              "IsString": false,  
195:              "IsSymbol": false,  
196:              "IsFunction": true,  
197:              "IsArray": false,  
198:              "IsObject": true,  
199:              "IsBoolean": false,  
200:              "IsNumber": false,  
201:              "IsExternal": false,  
202:              "IsInt32": false,  
203:              "IsUint32": false,  
204:              "IsDate": false,  
205:              "IsArgumentsObject": false,  
206:              "IsBooleanObject": false,  
207:              "IsNumberObject": false,  
208:              "IsStringObject": false,  
209:              "IsSymbolObject": false,  
210:              "IsNativeError": false,  
211:              "IsRegExp": false,  
212:              "IsGeneratorFunction": false,  
213:              "IsGeneratorObject": false,  
214:              "IsPromise": false,  
215:              "IsMap": false,  
216:              "IsSet": false,  
217:              "IsMapIterator": false,  
218:              "IsSetIterator": false,  
219:              "IsWeakMap": false,  
220:              "IsWeakSet": false,  
221:              "IsArrayBuffer": false,  
222:              "IsArrayBufferView": false,  
223:              "IsTypedArray": false,  
224:              "IsUint8Array": false,  
225:              "IsUint8ClampedArray": false,  
226:              "IsInt8Array": false,  
227:              "IsUint16Array": false,  
228:              "IsInt16Array": false,  
229:              "IsUint32Array": false,  
230:              "IsInt32Array": false,  
231:              "IsFloat32Array": false,  
232:              "IsFloat64Array": false,  
233:              "IsDataView": false,  
234:              "IsSharedArrayBuffer": false,  
235:              "IsProxy": false,  
236:              "ToBoolean": true,  
237:              "ToNumber": null,  
238:              "ToString": "function () {}",  
239:              "ToDetailString": "function () {}",  
240:              "ToInteger": 0,  
241:              "ToUint32": 0,  
242:              "ToInt32": 0,  
243:              "BooleanValue": true,  
244:              "NumberValue": null,  
245:              "IntegerValue": 0,  
246:              "Uint32Value": 0,  
247:              "Int32Value": 0,  
248:              "PropertyNames": [],  
249:              "GetConstructorName": "Function",  
250:              "InternalFieldCount": 0,  
251:              "HasNamedLookupInterceptor": false,  
252:              "HasIndexedLookupInterceptor": false,  
253:              "GetIdentityHash": 1329899702,  
254:              "IsCallable": true  
255:          },  
256:          "IsBoolean": false,  
257:          "IsNumber": false,  
258:          "IsExternal": false,  
259:          "IsInt32": false,  
260:          "IsUint32": false,  
261:          "IsDate": false,  
262:          "IsArgumentsObject": false,  
263:          "IsBooleanObject": false,  
264:          "IsNumberObject": false,  
265:          "IsStringObject": false,  
266:          "IsSymbolObject": false,  
267:          "IsNativeError": false,  
268:          "IsRegExp": false,  
269:          "IsGeneratorFunction": false,  
270:          "IsGeneratorObject": false,  
271:          "IsPromise": false,  
272:          "IsMap": false,  
273:          "IsSet": false,  
274:          "IsMapIterator": false,  
275:          "IsSetIterator": false,  
276:          "IsWeakMap": false,  
277:          "IsWeakSet": false,  
278:          "IsArrayBuffer": false,  
279:          "IsArrayBufferView": false,  
280:          "IsTypedArray": false,  
281:          "IsUint8Array": false,  
282:          "IsUint8ClampedArray": false,  
283:          "IsInt8Array": false,  
284:          "IsUint16Array": false,  
285:          "IsInt16Array": false,  
286:          "IsUint32Array": false,  
287:          "IsInt32Array": false,  
288:          "IsFloat32Array": false,  
289:          "IsFloat64Array": false,  
290:          "IsDataView": false,  
291:          "IsSharedArrayBuffer": false,  
292:          "IsProxy": false,  
293:          "ToBoolean": true,  
294:          "ToNumber": null,  
295:          "ToString": "function base_class() { [native code] }",  
296:          "ToDetailString": "function base_class() { [native code] }",  
297:          "ToInteger": 0,  
298:          "ToUint32": 0,  
299:          "ToInt32": 0,  
300:          "BooleanValue": true,  
301:          "NumberValue": null,  
302:          "IntegerValue": 0,  
303:          "Uint32Value": 0,  
304:          "Int32Value": 0  
305:      },  
306:      "Info": []  
307:  }  

There are many more parameters to explore, how does it show when an object is a child of another object? is there really an "int64" value in v8? spoiler: no. Can you do a ToInt32 on float numbers? What's the value of NumberValue for a particular string?

Have fun exploring :-)


Tuesday, July 19, 2016

ABS Linear Bearings

After many prints, my printer started making loud noise when printing and more and more striping, I've jiggled the X and Y axis and it was shaking much. I've guessed its the linear bearings and ordered replacements but how do I go on printing now?

Not long ago I've read about sort of plastic linear bearings, igus. Though it is interesting, it doesn't solve my problem at this minute and I need a solution now.

I've started looking into other solutions on thingiverse and eventually decided to try my own design

My Linear Bearing
The design is for grease, there is a spiral inside it with holes that go from top to bottom, so when too much grease accumulates on one side, it will be pushed back to the other.

I've used white ABS with 0.2mm nozzle and printed them very slow so the bad bearing won't shake too much. I've read that if the bearing are too tight, you can use acetone on the rods to loosen them up. 

After many hours of printing, they still work pretty well!

Without the seal



Saturday, June 25, 2016

Capacitive Sensor for Auto Bed Leveling

Leveling the printing bed is time consuming, move the printer, adjust any of the axises, move any of the Z axis motors and the printing bed is no longer level.

Add to this that I've recently added a glass printing bed that needs to be removed and replaced once in a while and bed leveling becomes a non pleasant task and wasted time.

The solution is auto bed leveling.

There are 3 main types of sensors, induction, capactive and some sort of touch, which is based on movement of a material, metal pushing on a switch, hall effect sensor or optical.

Other less common sensors could be distance sensors based on light or sound, but are not accurate enough for this purpose.

I've ruled out induction sensor since my print bed is now glass and induction sensors works only with metals but the concept is pretty similar. So I've selected the LJC18A3-H-Z/BX capacitive sensor for my tests.

The easiest proximity sensor to use is a switch since it interfaces directly to the controller without any circuitry, but the 2nd best sensor is NPN transistors since the MKS boards have a pullup and NPN connects the signal to ground when active, otherwise its considered floating, that's why a voltage divider works.

So I made a resistor voltage divider, you can use this calculator for initial values. Always use a multimeter to verify the output voltage is not over 5v otherwise you might burn the input pin or worse, the whole controller. also, if you use lower values for voltage divider you might ruin the proximity sensor, a good starting point is 15k/10k resistors for 12v. 

Again, measure, measure, measure! Like the old carpentry saying goes, measure twice, cut once.

Another thing to note is that the NPN sensors might display the status led always on if you connect the voltage divider directly, you can add a diode between the divider and the signal pin from the sensor, for example, anything in the 1N400X series would do.

After I've built the mini circuit and made sure the output voltage has the desired values (0v/5v) I went ahead and printed the proximity sensor bracket that connects to the fan/printing head assembly and made sure the printer can home the Z axis based on the proximity sensor.


There are two adjustments possible with this bracket, first, the height of the sensor from the print bed. My setup had a limitation since I've used bull clips to hold my glass on the build plate and the proximity would crash on the handle, so I've adjusted them as close as I could. In general the closer the capacitive sensor to the build plate, the more accurate the activation.


Another adjustment is the activation potentiometer on top of the sensor



Lastly, the z height in Marlin, which can be set in Configuration.h or in the menus (Control->Motion->Z Offset).

Combined, all these parameters will set the distance from nozzle to build plate. But to use the probe to home the printer, you'll need to issue G28 - home.

To actually autolevel the printer, we need to issue G29, which will probe multiple points on the build plate and create an adjustment matrix for the bed.

If you issue G29 without G28, it won't do anything, if you issue G29 without support in the firmware, same result, which is how my printer came configured, so I had to flash the firmware with autolevel support.

To do that, you need to have Arduino Software and get the sources from Marlin. You can find some explanations from here or use the documentation from Marlin's website.

There are explanations about autoleveling and configuration, but from my experience, less is more, I'm using 4 point grid on the outer edges of the bed, for glass its good enough, also, I recommend adding babystepping which helps you to fine tune the height when the print starts.

Probably the most important settings should be the board type, which tells marlin which pins are assigned to which input/output (motors/sensors/servos etc'), the temperature sensor settings, the steps per unit which indicate how many pulses to the stepper motor equals a millimeter, the max feedrate which indicates how fast the axises can move and the acceleration, which is depends on the weight of the print head carriage, you can reduce vibration and skipping and/or increase quality with lower values. The best way to figure it out is experiment.

You can find steps per unit calculator here and you can find multiple calibration structures here, each one for its own purpose, accuracy, speed, temperature, bridges, etc'

Good Luck! :-)

Saturday, May 21, 2016

Printing Flexible Filament

Apparently printing flexible filaments is not so simple :-)

When I first tried, the filament would bend inside the extruder and not even reach the hotend, if it did, it would drip. 

So the first step is to make the extruder push the filament, I've designed an extruder block that accurately fits on the extruder gear so it couldn't bend anywhere.


Partial success, the filament sometimes sticks inside the hotend when retraction is enabled, so next step is to disable the retraction.

Now I can print some stuff, like rubber legs for my tripod!


Monday, March 7, 2016

Parsing OpenCV C++ Code/Headers

I wanted to create a wrapper of OpenCV for Node js, I've looked at it from different angles as I didn't want to write it by hand, since I had an idea about making it multithreaded and easy to use with typescript bindings.

There's an already existing project called node-opencv but a lot of its functions are not suitable for multithreading or async javascript programming, which is what I aimed for.


hdr_parser.py   

OpenCV's way of exposing the OpenCV api for python is using hdr_parser.py, which goes over the headers and exports a list of functions then needed to be made into python code with gen2.py

The exported list looks something like this:

cv.groupRectangles void
    vector_Rect rectList /IO
    vector_int weights /O
    int groupThreshold
    double eps 0.2
const cv.CASCADE_DO_CANNY_PRUNING 1
const cv.CASCADE_SCALE_IMAGE 2
const cv.CASCADE_FIND_BIGGEST_OBJECT 4
const cv.CASCADE_DO_ROUGH_SEARCH 8
class cv.BaseCascadeClassifier : cv::Algorithm
class cv.CascadeClassifier
cv.CascadeClassifier.CascadeClassifier
cv.CascadeClassifier.CascadeClassifier
    String filename
cv.CascadeClassifier.empty bool
cv.CascadeClassifier.load bool
    String filename
cv.CascadeClassifier.read bool
    FileNode node
cv.CascadeClassifier.detectMultiScale void
    Mat image
    vector_Rect objects /O
    double scaleFactor 1.1
    int minNeighbors 3
    int flags 0
    Size minSize Size()
    Size maxSize Size()

Which isn't so much useful if I'd like to do something more complex such as creating all the functions with their enums as parameters or creating setters and getters instead of get/set functions, but it could be the way OpenCV is written.


PEG.JS

So I've decided to try and parse the headers myself, I've found a PEG.js C++ parser written by Pau Fernández and decided to give it a go, the first execution was terrible, most of the header files couldn't be parsed and I've spent a few days fixing about 80% of it to finish parsing, with some days getting so frustrated that I've even tried to rebuild it myself.

But then I've read somewhere that the problem with C++ parsing expression grammar is that they lack context, so eventually I had to move on and try a different approach.

But before I moved on, I ended up with a nice tool to help me work on that grammar


antlr4

In search of a C++ parser, I've met antlr4, it looked nice and it had many grammars, one of them is C++, while working on that direction, I did not find it suitable, as the learning curve was stiffer than I wanted to invest at the moment.

antlr4 c++ grammer can be found here and the office javascript antlr4 documentation is here.

You can compile the grammer to javascript:

antlr4 -Dlanguage=JavaScript CPP14.g4

or if you would like a visitor:

antlr4 -Dlanguage=JavaScript -visitor CPP14.g4


LLVM

LLVM is a compiler, you can dump the AST. but since it's also directed at full compilation, figuring what you need to take from it is out of the scope of my needs.

You can dump the ast with this command:

clang -cc1 -ast-dump file.c


castxml

castxml is a tool that parses C++ files and generates XML AST, before castxml there was GCC-XML, both were written by Brad King from Kitware who are responsible for some major open source projects such as VTK, CMake and ITK.

castxml showed the most promise, I got to know it after I saw this brief presentation by Matthew MaCormick and looked at the output.

Eventually I decided its time to try it, so I've downloaded it.

It has llvm includes directory and gave it a shot with this command arguments:

castxml.exe --castxml-gccxml -o output.xml "header.hpp" -I includefolder ...

and the entire AST was generated and human readable.
After a bit of manipulation with xml2js, I got the following result:

{ id: '_3119',
       name: 'Cv_iplAllocateImageData',
       type: { id: '_8779', type: [Object], elementtype: 'PointerType' },
       context: [Circular],
       location: 'f66:1938',
       file: 'f66',
       line: '1938',
       elementtype: 'Typedef' },
  { id: '_3120',
       name: 'Cv_iplDeallocate',
       type: { id: '_8780', type: [Object], elementtype: 'PointerType' },
       context: [Circular],
       location: 'f66:1939',
       file: 'f66',
       line: '1939',
       elementtype: 'Typedef' },

from which it was easy to derive:

void filter2D ( InputArray src,  OutputArray dst,  int ddepth,  InputArray kernel,  Point anchor,  double delta,  int borderType );
void sepFilter2D ( InputArray src,  OutputArray dst,  int ddepth,  InputArray kernelX,  InputArray kernelY,  Point anchor,  double delta,  int borderType );
void Sobel ( InputArray src,  OutputArray dst,  int ddepth,  int dx,  int dy,  int ksize,  double scale,  double delta,  int borderType );

Which was pretty neat!

The best part about it, since it went through the llvm compiler and preprocessor, the only exported functions, structures and classes were those that are actually compiled in the real project without any extra work.

please note a few things about castxml:

- it works only with --castxml-gccxml flag, without it, it will compile but not work.
- llvm relies on file extension to distinguish between c and c++ headers, to force it to use c++ compiler for h extension use the "-c c++" argument.
- compiling on windows might throw some errors, it could be because ms vc++ headers rely on a version passed to the compiler, use "-fms-compatibility-version=19.00".
- if you're using exceptions in your code make sure you tell it to llvm as it has exceptions disabled by default "-fexceptions"

bonus: ITK has a module that converts the castxml output to swig 

extra bonus: I've created a parser tool to help me out with the xml file, you can find it here.


swig

Swig actually looks like a perfect tool for this job, it has both V8 and Node js targets, but I wanted a node js with nan target with async workers and multithreaded queuing in libuv and safety locks (mutexes), which I'll probably have to implement into the default swig templates.

At the moment it looks like the best tool for the job but I'm not sure how easy it's going to be to create nan template over regular macros.


For now I'm exploring a combination of castxml and macros, if you think there's a better way, I'll be glad to know about it.