Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: compiled/bindings.ipp

Issue 29384812: Issue 4127 - [emscripten] Convert subscription classes to C++ - Part 1 (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore
Left Patch Set: Fixed method names according to convention Created March 16, 2017, 6:26 p.m.
Right Patch Set: Addressed comments Created April 13, 2017, 1:02 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « compiled/bindings.cpp ('k') | compiled/filter/Filter.h » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2017 eyeo GmbH
4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */
17
1 #pragma once 18 #pragma once
2 19
20 #include <cstddef>
3 #include <cstdint> 21 #include <cstdint>
4 #include <cstdio> 22 #include <cstdio>
5 #include <cstdlib> 23 #include <cstdlib>
6 #include <exception> 24 #include <exception>
7 #include <map> 25 #include <map>
8 #include <string> 26 #include <string>
9 #include <type_traits> 27 #include <type_traits>
10 #include <utility> 28 #include <utility>
11 #include <vector> 29 #include <vector>
12 30
13 #include <emscripten.h> 31 #include <emscripten.h>
14 32
15 #include "String.h" 33 #include "String.h"
16 #include "intrusive_ptr.h" 34 #include "intrusive_ptr.h"
17 35
18 namespace bindings_internal 36 namespace bindings_internal
19 { 37 {
20 typedef void* TYPEID; 38 typedef void* TYPEID;
21 39
22 enum class TypeCategory 40 enum class TypeCategory
23 { 41 {
24 UNKNOWN, 42 UNKNOWN,
25 VOID, 43 VOID,
26 INT, 44 INT,
45 INT64,
27 FLOAT, 46 FLOAT,
47 DOUBLE,
28 DEPENDENT_STRING, 48 DEPENDENT_STRING,
29 OWNED_STRING, 49 OWNED_STRING,
30 STRING_REF, 50 STRING_REF,
31 CLASS_PTR 51 CLASS_PTR
32 }; 52 };
33 53
34 template<typename T> 54 template<typename T>
35 struct TypeInfo 55 struct TypeInfo
36 { 56 {
37 /* 57 /*
38 * Since TypeInfo is a templated type, in practice the compiler will define 58 * Since TypeInfo is a templated type, in practice the compiler will define
39 * a new type for each possible template parameter value. We use that fact 59 * a new type for each possible template parameter value. We use that fact
40 * to generate type identifiers: each of these TypeInfo types has a 60 * to generate type identifiers: each of these TypeInfo types has a
41 * different s_typeIDHelper member, so we use a pointer to that static 61 * different s_typeIDHelper member, so we use a pointer to that static
42 * variable as a type identifier - it will be different for each template 62 * variable as a type identifier - it will be different for each template
43 * parameter. 63 * parameter.
44 */ 64 */
45 static char s_typeIDHelper; 65 static char s_typeIDHelper;
46 constexpr operator TYPEID() const 66 constexpr operator TYPEID() const
47 { 67 {
48 return &s_typeIDHelper; 68 return &s_typeIDHelper;
49 } 69 }
50 70
51 constexpr operator TypeCategory() const 71 constexpr operator TypeCategory() const
52 { 72 {
53 if (std::is_void<T>()) 73 if (std::is_void<T>())
54 return TypeCategory::VOID; 74 return TypeCategory::VOID;
55 75
76 if (std::is_same<T, uint64_t>())
77 return TypeCategory::INT64;
78
56 if (std::is_integral<T>() || std::is_enum<T>()) 79 if (std::is_integral<T>() || std::is_enum<T>())
57 return TypeCategory::INT; 80 return TypeCategory::INT;
58 81
59 if (std::is_floating_point<T>()) 82 if (std::is_same<T, float>())
60 return TypeCategory::FLOAT; 83 return TypeCategory::FLOAT;
84
85 if (std::is_same<T, double>())
86 return TypeCategory::DOUBLE;
61 87
62 if (std::is_same<DependentString, T>() || std::is_same<const DependentStri ng, T>()) 88 if (std::is_same<DependentString, T>() || std::is_same<const DependentStri ng, T>())
63 return TypeCategory::DEPENDENT_STRING; 89 return TypeCategory::DEPENDENT_STRING;
64 90
65 if (std::is_same<OwnedString, T>() || std::is_same<const OwnedString, T>() ) 91 if (std::is_same<OwnedString, T>() || std::is_same<const OwnedString, T>() )
66 return TypeCategory::OWNED_STRING; 92 return TypeCategory::OWNED_STRING;
67 93
68 if (std::is_same<String&, T>() || std::is_same<const String&, T>() || 94 if (std::is_same<String&, T>() || std::is_same<const String&, T>() ||
69 std::is_same<DependentString&, T>()) 95 std::is_same<DependentString&, T>())
70 { 96 {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 instance_function(instance_function) 137 instance_function(instance_function)
112 { 138 {
113 name[0] = '\0'; 139 name[0] = '\0';
114 140
115 // The function parameter is a pointer to the function pointer. 141 // The function parameter is a pointer to the function pointer.
116 // Emscripten's "function pointers" are actually integers indicating the 142 // Emscripten's "function pointers" are actually integers indicating the
117 // position in the call table. 0 represents nullptr. 143 // position in the call table. 0 represents nullptr.
118 if (!*reinterpret_cast<int*>(function)) 144 if (!*reinterpret_cast<int*>(function))
119 return; 145 return;
120 146
121 char signature[256]; 147 std::string signature;
122 int pos = 0; 148
123 if (returnType == TypeCategory::DEPENDENT_STRING || 149 // Add return type to the signature. Similar logic in Emscripten:
124 returnType == TypeCategory::OWNED_STRING) 150 // https://github.com/kripken/emscripten/blob/1.37.3/src/modules.js#L46
125 { 151 switch (returnType)
126 // Objects aren't really returned but passed as parameter. Note that 152 {
127 // this pointer might come before it but we don't care because both 153 case TypeCategory::DEPENDENT_STRING:
128 // are integers (pointers) as far as Emscripten is concerned. 154 case TypeCategory::OWNED_STRING:
129 signature[pos++] = 'v'; 155 // Technically, objects aren't really returned with clang. The caller
130 signature[pos++] = 'i'; 156 // instead adds the reference to the resulting object as an implicit
131 } 157 // parameter.
132 else if (returnType == TypeCategory::VOID) 158 signature += "vi";
133 signature[pos++] = 'v'; 159 break;
134 else if (returnType == TypeCategory::FLOAT) 160 case TypeCategory::VOID:
135 signature[pos++] = 'd'; 161 signature += 'v';
136 else if (returnType == TypeCategory::INT || 162 break;
137 returnType == TypeCategory::STRING_REF || 163 case TypeCategory::FLOAT:
138 returnType == TypeCategory::CLASS_PTR) 164 signature += 'f';
139 { 165 break;
140 signature[pos++] = 'i'; 166 case TypeCategory::DOUBLE:
141 } 167 signature += 'd';
142 else 168 break;
143 throw std::runtime_error("Unexpected function return type"); 169 case TypeCategory::INT:
144 170 case TypeCategory::INT64:
171 case TypeCategory::STRING_REF:
172 case TypeCategory::CLASS_PTR:
173 signature += 'i';
174 break;
175 default:
176 throw std::runtime_error("Unexpected function return type");
177 }
178
179 // `this` pointer is an implicit parameter with clang and should be added
180 // to the signature.
145 if (instance_function) 181 if (instance_function)
146 { 182 signature += 'i';
147 // this pointer is an implicit parameter 183
148 signature[pos++] = 'i'; 184 // Add explicit parameters to the signature, Similar logic in Emscripten:
149 } 185 // https://github.com/kripken/emscripten/blob/1.37.3/src/modules.js#L67
150 186 for (const auto& type : argTypes)
151 for (const auto& item : argTypes) 187 {
152 { 188 switch (type)
153 if (item == TypeCategory::INT || item == TypeCategory::STRING_REF ||
154 item == TypeCategory::CLASS_PTR)
155 { 189 {
156 signature[pos++] = 'i'; 190 case TypeCategory::INT:
191 case TypeCategory::STRING_REF:
192 case TypeCategory::CLASS_PTR:
193 signature += 'i';
194 break;
195 case TypeCategory::INT64:
196 // See https://github.com/kripken/emscripten/blob/1.37.3/src/modules .js#L73,
197 // numerical types larger than 32-bit are split into multiple
198 // 32-bit parameters.
199 signature += "ii";
200 break;
201 case TypeCategory::FLOAT:
202 signature += 'f';
203 break;
204 case TypeCategory::DOUBLE:
205 signature += 'd';
206 break;
207 default:
208 throw std::runtime_error("Unexpected function argument type");
157 } 209 }
158 else if (item == TypeCategory::FLOAT) 210 args.push_back(type);
159 signature[pos++] = 'd'; 211 }
160 else 212
161 throw std::runtime_error("Unexpected function argument type"); 213 get_function_name(function, signature.c_str());
162 args.push_back(item);
163 }
164
165 signature[pos] = 0;
166
167 get_function_name(function, signature);
168 } 214 }
169 215
170 template<typename ReturnType, typename... Args> 216 template<typename ReturnType, typename... Args>
171 FunctionInfo(ReturnType (*function)(Args...)) 217 FunctionInfo(ReturnType (*function)(Args...))
172 : FunctionInfo(TypeInfo<ReturnType>(), 218 : FunctionInfo(TypeInfo<ReturnType>(),
173 TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, false, 219 TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, false,
174 &function) 220 &function)
175 { 221 {
176 } 222 }
177 223
(...skipping 11 matching lines...) Expand all
189 TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, true, 235 TypeInfo<ReturnType>().pointer_type(), { TypeInfo<Args>()... }, true,
190 &function) 236 &function)
191 { 237 {
192 } 238 }
193 239
194 bool empty() const 240 bool empty() const
195 { 241 {
196 return name[0] == '\0'; 242 return name[0] == '\0';
197 } 243 }
198 244
199 void get_function_name(void* ptr, char* signature) 245 void get_function_name(void* ptr, const char* signature)
200 { 246 {
201 // This is a hack, C++ won't let us get the mangled function name. 247 // This is a hack, C++ won't let us get the mangled function name.
202 // JavaScript is more dynamic so we pass the pointer to our function 248 // JavaScript is more dynamic so we pass the pointer to our function
203 // there. With that and the function signature we can call the function - 249 // there. With that and the function signature we can call the function -
204 // with a full stack so that we will cause it to abort. Sometimes the 250 // with a full stack so that we will cause it to abort. Sometimes the
205 // function we are calling will also be missing from the build. The result 251 // function we are calling will also be missing from the build. The result
206 // is the same: abort() is called which in turn calls stackTrace(). By 252 // is the same: abort() is called which in turn calls stackTrace(). By
207 // replacing stackTrace() we get access to the call stack and search it 253 // replacing stackTrace() we get access to the call stack and search it
208 // for the name of our function. 254 // for the name of our function.
209 255
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 }; 331 };
286 332
287 struct ClassInfo 333 struct ClassInfo
288 { 334 {
289 ClassInfo* baseClass; 335 ClassInfo* baseClass;
290 std::string name; 336 std::string name;
291 std::vector<PropertyInfo> properties; 337 std::vector<PropertyInfo> properties;
292 std::vector<MethodInfo> methods; 338 std::vector<MethodInfo> methods;
293 std::vector<FunctionInfo> initializers; 339 std::vector<FunctionInfo> initializers;
294 DifferentiatorInfo subclass_differentiator; 340 DifferentiatorInfo subclass_differentiator;
295 int ref_counted_offset; 341 ptrdiff_t ref_counted_offset;
296 }; 342 };
297 343
298 std::map<TYPEID, ClassInfo> classes; 344 std::map<TYPEID, ClassInfo> classes;
299 345
300 void register_class(const char* name, TYPEID classID, TYPEID baseClassID, 346 void register_class(const char* name, TYPEID classID, TYPEID baseClassID,
301 int ref_counted_offset) 347 ptrdiff_t ref_counted_offset)
302 { 348 {
303 auto it = classes.find(classID); 349 auto it = classes.find(classID);
304 if (it != classes.end()) 350 if (it != classes.end())
305 throw std::runtime_error(std::string("Duplicate definition for class ") + name); 351 throw std::runtime_error(std::string("Duplicate definition for class ") + name);
306 352
307 ClassInfo* baseClass = nullptr; 353 ClassInfo* baseClass = nullptr;
308 if (baseClassID != TypeInfo<NoBaseClass>()) 354 if (baseClassID != TypeInfo<NoBaseClass>())
309 { 355 {
310 it = classes.find(baseClassID); 356 it = classes.find(baseClassID);
311 if (it == classes.end()) 357 if (it == classes.end())
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 std::string call_str(call.name); 433 std::string call_str(call.name);
388 call_str += "("; 434 call_str += "(";
389 for (int i = 0; i < params.size(); i++) 435 for (int i = 0; i < params.size(); i++)
390 { 436 {
391 if (i > 0) 437 if (i > 0)
392 call_str += ", "; 438 call_str += ", ";
393 call_str += params[i]; 439 call_str += params[i];
394 } 440 }
395 call_str += ")"; 441 call_str += ")";
396 442
397 if (call.returnType == TypeCategory::VOID) 443 switch (call.returnType)
398 return " " + call_str + ";\n"; 444 {
399 else if (call.returnType == TypeCategory::INT || 445 case TypeCategory::VOID:
400 call.returnType == TypeCategory::FLOAT) 446 return " " + call_str + ";\n";
401 { 447 case TypeCategory::INT:
402 return " var result = " + call_str + ";\n"; 448 case TypeCategory::FLOAT:
403 } 449 case TypeCategory::DOUBLE:
404 else if (call.returnType == TypeCategory::DEPENDENT_STRING || 450 return " var result = " + call_str + ";\n";
405 call.returnType == TypeCategory::OWNED_STRING) 451 case TypeCategory::INT64:
406 { 452 return " var result = Runtime.makeBigInt(" + call_str + ", " +
407 std::string result; 453 "Runtime.getTempRet0(), " +
408 result += " var string = createString();\n"; 454 "true);\n";
409 result += " " + call_str + ";\n"; 455 case TypeCategory::DEPENDENT_STRING:
410 result += " var result = readString(string);\n"; 456 case TypeCategory::OWNED_STRING:
411 if (call.returnType == TypeCategory::OWNED_STRING) 457 {
412 result += " Module._DestroyString(string);\n"; 458 std::string result;
413 return result; 459 result += " var string = createString();\n";
414 } 460 result += " " + call_str + ";\n";
415 else if (call.returnType == TypeCategory::STRING_REF) 461 result += " var result = readString(string);\n";
416 { 462 if (call.returnType == TypeCategory::OWNED_STRING)
417 return " var result = readString(" + call_str + ");\n"; 463 result += " Module._DestroyString(string);\n";
418 } 464 return result;
419 else if (call.returnType == TypeCategory::CLASS_PTR) 465 }
420 { 466 case TypeCategory::STRING_REF:
421 std::string result; 467 return " var result = readString(" + call_str + ");\n";
422 result += " var result = " + call_str + ";\n"; 468 case TypeCategory::CLASS_PTR:
423 result += " if (result)\n"; 469 {
424 result += " {\n"; 470 std::string result;
425 471 result += " var result = " + call_str + ";\n";
426 auto it = classes.find(call.pointerType); 472 result += " if (result)\n";
427 if (it == classes.end()) 473 result += " {\n";
428 throw std::runtime_error("Function " + std::string(call.name) + " return s pointer to unknown class"); 474
429 475 auto it = classes.find(call.pointerType);
430 const ClassInfo& cls = it->second; 476 if (it == classes.end())
431 auto offset = cls.subclass_differentiator.offset; 477 throw std::runtime_error("Function " + std::string(call.name) + " retu rns pointer to unknown class");
432 if (offset == SIZE_MAX) 478
433 result += " result = " + cls.name + "(result);\n"; 479 const ClassInfo& cls = it->second;
434 else 480 auto offset = cls.subclass_differentiator.offset;
435 { 481 if (offset == SIZE_MAX)
436 result += " var type = HEAP32[result + " + std::to_string(offset)+ " >> 2];\n"; 482 result += " result = " + cls.name + "(result);\n";
437 result += " if (type in " + cls.name + "_mapping)\n"; 483 else
438 result += " result = new (exports[" + cls.name + "_mapping[type]])( result);\n"; 484 {
439 result += " else\n"; 485 result += " var type = HEAP32[result + " + std::to_string(offset)+ " >> 2];\n";
440 result += " throw new Error('Unexpected " + cls.name + " type: ' + type);\n"; 486 result += " if (type in " + cls.name + "_mapping)\n";
441 } 487 result += " result = new (exports[" + cls.name + "_mapping[type]] )(result);\n";
442 488 result += " else\n";
443 result += " }\n"; 489 result += " throw new Error('Unexpected " + cls.name + " type: ' + type);\n";
444 return result; 490 }
445 } 491
446 else 492 result += " }\n";
447 throw std::runtime_error("Unexpected return type for " + std::string(call. name)); 493 return result;
494 }
495 default:
496 throw std::runtime_error("Unexpected return type for " + std::string(cal l.name));
497 }
448 } 498 }
449 499
450 const std::string wrapCall(const FunctionInfo& call) 500 const std::string wrapCall(const FunctionInfo& call)
451 { 501 {
452 char buffer[20];
453 bool hasStringArgs = false; 502 bool hasStringArgs = false;
454 std::vector<std::string> params; 503 std::vector<std::string> params;
455 std::string prefix = "function("; 504 std::string prefix = "function(";
456 for (int i = 0; i < call.args.size(); i++) 505 for (int i = 0; i < call.args.size(); i++)
457 { 506 {
458 sprintf(buffer, "arg%i", i); 507 std::string argName("arg" + std::to_string(i));
459 if (i > 0) 508 if (i > 0)
460 prefix += ", "; 509 prefix += ", ";
461 prefix += buffer; 510 prefix += argName;
462 511
463 if (call.args[i] == TypeCategory::STRING_REF) 512 if (call.args[i] == TypeCategory::STRING_REF)
464 { 513 {
465 hasStringArgs = true; 514 hasStringArgs = true;
466 params.push_back(std::string("createString(") + buffer + ")"); 515 params.push_back(std::string("createString(") + argName + ")");
467 } 516 }
468 else if (call.args[i] == TypeCategory::CLASS_PTR) 517 else if (call.args[i] == TypeCategory::CLASS_PTR)
469 params.push_back(std::string(buffer) + "._pointer"); 518 params.push_back(argName + "._pointer");
519 else if (call.args[i] == TypeCategory::INT64)
520 {
521 // 64-bit integers are passed as two integer parameters
522 params.push_back(argName + " >>> 0");
523 params.push_back(argName + " / 0x100000000 >>> 0");
524 }
470 else 525 else
471 params.push_back(buffer); 526 params.push_back(argName);
472 } 527 }
473 prefix += ")\n{\n"; 528 prefix += ")\n{\n";
474 529
475 std::string suffix = "}"; 530 std::string suffix = "}";
476 if (call.returnType != TypeCategory::VOID) 531 if (call.returnType != TypeCategory::VOID)
477 suffix = " return result;\n" + suffix; 532 suffix = " return result;\n" + suffix;
478 533
479 if (call.returnType == TypeCategory::DEPENDENT_STRING || 534 if (call.returnType == TypeCategory::DEPENDENT_STRING ||
480 call.returnType == TypeCategory::OWNED_STRING || hasStringArgs) 535 call.returnType == TypeCategory::OWNED_STRING || hasStringArgs)
481 { 536 {
(...skipping 16 matching lines...) Expand all
498 if (!property.setter.empty()) 553 if (!property.setter.empty())
499 result += ", set: " + wrapCall(property.setter); 554 result += ", set: " + wrapCall(property.setter);
500 return result; 555 return result;
501 } 556 }
502 557
503 void printHelpers() 558 void printHelpers()
504 { 559 {
505 printf("var sizeofString = %i;\n", sizeof(String)); 560 printf("var sizeofString = %i;\n", sizeof(String));
506 561
507 puts(R"( 562 puts(R"(
508 function copyString(str, buffer) 563 function copyString(str, buffer)
509 { 564 {
510 var length = str.length; 565 var length = str.length;
511 for (var i = 0, pointer = (buffer >> 1); i < length; i++, pointer++) 566 for (var i = 0, pointer = (buffer >> 1); i < length; i++, pointer++)
512 HEAP16[pointer] = str.charCodeAt(i); 567 HEAP16[pointer] = str.charCodeAt(i);
513 return length; 568 return length;
514 } 569 }
515 570
516 function createString(str) 571 function createString(str)
517 { 572 {
518 var length = 0; 573 var length = 0;
519 var buffer = 0; 574 var buffer = 0;
520 if (str) 575 if (str)
521 { 576 {
522 buffer = Runtime.stackAlloc(str.length * 2); 577 buffer = Runtime.stackAlloc(str.length * 2);
523 length = copyString(str, buffer); 578 length = copyString(str, buffer);
524 } 579 }
525 580
526 var result = Runtime.stackAlloc(sizeofString); 581 var result = Runtime.stackAlloc(sizeofString);
527 Module._InitString(result, buffer, length); 582 Module._InitString(result, buffer, length);
528 return result; 583 return result;
529 } 584 }
530 585
531 function readString(str) 586 function readString(str)
532 { 587 {
533 var length = Module._GetStringLength(str); 588 var length = Module._GetStringLength(str);
534 var pointer = Module._GetStringData(str) >> 1; 589 var pointer = Module._GetStringData(str) >> 1;
535 return String.fromCharCode.apply(String, HEAP16.slice(pointer, pointer + len gth)); 590 return String.fromCharCode.apply(String, HEAP16.slice(pointer, pointer + length));
536 } 591 }
537 592
538 function createClass(superclass, ref_counted_offset) 593 function createClass(superclass, ref_counted_offset)
539 { 594 {
540 var result = function(pointer) 595 var result = function(pointer)
541 { 596 {
542 this._pointer = pointer; 597 this._pointer = pointer;
543 }; 598 };
544 if (superclass) 599 if (superclass)
545 result.prototype = Object.create(superclass.prototype); 600 result.prototype = Object.create(superclass.prototype);
546 result.prototype.delete = function() 601 result.prototype.delete = function()
547 { 602 {
548 Module._ReleaseRef(this._pointer + ref_counted_offset); 603 Module._ReleaseRef(this._pointer + ref_counted_offset);
549 }; 604 };
550 return result; 605 return result;
551 } 606 }
552 )"); 607 )");
553 } 608 }
554 609
555 void printClass(const ClassInfo& cls) 610 void printClass(const ClassInfo& cls)
556 { 611 {
557 DifferentiatorInfo differentiator = cls.subclass_differentiator; 612 DifferentiatorInfo differentiator = cls.subclass_differentiator;
558 if (differentiator.offset != SIZE_MAX) 613 if (differentiator.offset != SIZE_MAX)
559 { 614 {
560 printf("var %s_mapping = \n", cls.name.c_str()); 615 printf("var %s_mapping = \n", cls.name.c_str());
561 puts("{"); 616 puts("{");
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
660 715
661 template<typename ClassType, 716 template<typename ClassType,
662 typename BaseClass = bindings_internal::NoBaseClass, 717 typename BaseClass = bindings_internal::NoBaseClass,
663 typename std::enable_if<std::is_base_of<ref_counted, ClassType>::value>::typ e* = nullptr> 718 typename std::enable_if<std::is_base_of<ref_counted, ClassType>::value>::typ e* = nullptr>
664 class class_ 719 class class_
665 { 720 {
666 public: 721 public:
667 class_(const char* name) 722 class_(const char* name)
668 { 723 {
669 ClassType* ptr = reinterpret_cast<ClassType*>(0x10000000); 724 ClassType* ptr = reinterpret_cast<ClassType*>(0x10000000);
670 int ref_counted_offset = 725 ptrdiff_t ref_counted_offset =
671 reinterpret_cast<int>(dynamic_cast<ref_counted*>(ptr)) - 726 reinterpret_cast<char*>(static_cast<ref_counted*>(ptr)) -
672 reinterpret_cast<int>(ptr); 727 reinterpret_cast<char*>(ptr);
673 bindings_internal::register_class(name, 728 bindings_internal::register_class(name,
674 bindings_internal::TypeInfo<ClassType>(), 729 bindings_internal::TypeInfo<ClassType>(),
675 bindings_internal::TypeInfo<BaseClass>(), 730 bindings_internal::TypeInfo<BaseClass>(),
676 ref_counted_offset 731 ref_counted_offset
677 ); 732 );
678 } 733 }
679 734
680 template<typename FieldType> 735 template<typename FieldType>
681 const class_& property(const char* name, 736 const class_& property(const char* name,
682 FieldType (ClassType::*getter)() const, 737 FieldType (ClassType::*getter)() const,
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
738 793
739 std::vector<std::pair<int, std::string>> mapping; 794 std::vector<std::pair<int, std::string>> mapping;
740 for (const auto& item : list) 795 for (const auto& item : list)
741 mapping.emplace_back(item.first, item.second); 796 mapping.emplace_back(item.first, item.second);
742 797
743 bindings_internal::register_differentiator( 798 bindings_internal::register_differentiator(
744 bindings_internal::TypeInfo<ClassType>(), offset, mapping); 799 bindings_internal::TypeInfo<ClassType>(), offset, mapping);
745 return *this; 800 return *this;
746 } 801 }
747 }; 802 };
LEFTRIGHT

Powered by Google App Engine
This is Rietveld