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

Delta Between Two Patch Sets: compiled/bindings.ipp

Issue 29385742: Issue 4127 - [emscripten] Convert subscription classes to C++ - Part 2 (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore
Left Patch Set: Created March 16, 2017, 6:27 p.m.
Right Patch Set: Rebased Created April 13, 2017, 1:01 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 result += " else\n"; 490 }
445 result += " result = null;\n"; 491
Wladimir Palant 2017/03/16 18:31:23 This isn't strictly necessary but expecting 0 as r
446 return result; 492 result += " }\n";
447 } 493 result += " else\n";
448 else 494 result += " result = null;\n";
449 throw std::runtime_error("Unexpected return type for " + std::string(call. name)); 495 return result;
496 }
497 default:
498 throw std::runtime_error("Unexpected return type for " + std::string(cal l.name));
499 }
450 } 500 }
451 501
452 const std::string wrapCall(const FunctionInfo& call) 502 const std::string wrapCall(const FunctionInfo& call)
453 { 503 {
454 char buffer[20];
455 bool hasStringArgs = false; 504 bool hasStringArgs = false;
456 std::vector<std::string> params; 505 std::vector<std::string> params;
457 std::string prefix = "function("; 506 std::string prefix = "function(";
458 for (int i = 0; i < call.args.size(); i++) 507 for (int i = 0; i < call.args.size(); i++)
459 { 508 {
460 sprintf(buffer, "arg%i", i); 509 std::string argName("arg" + std::to_string(i));
461 if (i > 0) 510 if (i > 0)
462 prefix += ", "; 511 prefix += ", ";
463 prefix += buffer; 512 prefix += argName;
464 513
465 if (call.args[i] == TypeCategory::STRING_REF) 514 if (call.args[i] == TypeCategory::STRING_REF)
466 { 515 {
467 hasStringArgs = true; 516 hasStringArgs = true;
468 params.push_back(std::string("createString(") + buffer + ")"); 517 params.push_back(std::string("createString(") + argName + ")");
469 } 518 }
470 else if (call.args[i] == TypeCategory::CLASS_PTR) 519 else if (call.args[i] == TypeCategory::CLASS_PTR)
471 params.push_back(std::string(buffer) + "._pointer"); 520 params.push_back(argName + "._pointer");
521 else if (call.args[i] == TypeCategory::INT64)
522 {
523 // 64-bit integers are passed as two integer parameters
524 params.push_back(argName + " >>> 0");
525 params.push_back(argName + " / 0x100000000 >>> 0");
526 }
472 else 527 else
473 params.push_back(buffer); 528 params.push_back(argName);
474 } 529 }
475 prefix += ")\n{\n"; 530 prefix += ")\n{\n";
476 531
477 std::string suffix = "}"; 532 std::string suffix = "}";
478 if (call.returnType != TypeCategory::VOID) 533 if (call.returnType != TypeCategory::VOID)
479 suffix = " return result;\n" + suffix; 534 suffix = " return result;\n" + suffix;
480 535
481 if (call.returnType == TypeCategory::DEPENDENT_STRING || 536 if (call.returnType == TypeCategory::DEPENDENT_STRING ||
482 call.returnType == TypeCategory::OWNED_STRING || hasStringArgs) 537 call.returnType == TypeCategory::OWNED_STRING || hasStringArgs)
483 { 538 {
(...skipping 16 matching lines...) Expand all
500 if (!property.setter.empty()) 555 if (!property.setter.empty())
501 result += ", set: " + wrapCall(property.setter); 556 result += ", set: " + wrapCall(property.setter);
502 return result; 557 return result;
503 } 558 }
504 559
505 void printHelpers() 560 void printHelpers()
506 { 561 {
507 printf("var sizeofString = %i;\n", sizeof(String)); 562 printf("var sizeofString = %i;\n", sizeof(String));
508 563
509 puts(R"( 564 puts(R"(
510 function copyString(str, buffer) 565 function copyString(str, buffer)
511 { 566 {
512 var length = str.length; 567 var length = str.length;
513 for (var i = 0, pointer = (buffer >> 1); i < length; i++, pointer++) 568 for (var i = 0, pointer = (buffer >> 1); i < length; i++, pointer++)
514 HEAP16[pointer] = str.charCodeAt(i); 569 HEAP16[pointer] = str.charCodeAt(i);
515 return length; 570 return length;
516 } 571 }
517 572
518 function createString(str) 573 function createString(str)
519 { 574 {
520 var length = 0; 575 var length = 0;
521 var buffer = 0; 576 var buffer = 0;
522 if (str) 577 if (str)
523 { 578 {
524 buffer = Runtime.stackAlloc(str.length * 2); 579 buffer = Runtime.stackAlloc(str.length * 2);
525 length = copyString(str, buffer); 580 length = copyString(str, buffer);
526 } 581 }
527 582
528 var result = Runtime.stackAlloc(sizeofString); 583 var result = Runtime.stackAlloc(sizeofString);
529 Module._InitString(result, buffer, length); 584 Module._InitString(result, buffer, length);
530 return result; 585 return result;
531 } 586 }
532 587
533 function readString(str) 588 function readString(str)
534 { 589 {
535 var length = Module._GetStringLength(str); 590 var length = Module._GetStringLength(str);
536 var pointer = Module._GetStringData(str) >> 1; 591 var pointer = Module._GetStringData(str) >> 1;
537 return String.fromCharCode.apply(String, HEAP16.slice(pointer, pointer + len gth)); 592 return String.fromCharCode.apply(String, HEAP16.slice(pointer, pointer + length));
538 } 593 }
539 594
540 function createClass(superclass, ref_counted_offset) 595 function createClass(superclass, ref_counted_offset)
541 { 596 {
542 var result = function(pointer) 597 var result = function(pointer)
543 { 598 {
544 this._pointer = pointer; 599 this._pointer = pointer;
545 }; 600 };
546 if (superclass) 601 if (superclass)
547 result.prototype = Object.create(superclass.prototype); 602 result.prototype = Object.create(superclass.prototype);
548 result.prototype.delete = function() 603 result.prototype.delete = function()
549 { 604 {
550 Module._ReleaseRef(this._pointer + ref_counted_offset); 605 Module._ReleaseRef(this._pointer + ref_counted_offset);
551 }; 606 };
552 return result; 607 return result;
553 } 608 }
554 )"); 609 )");
555 } 610 }
556 611
557 void printClass(const ClassInfo& cls) 612 void printClass(const ClassInfo& cls)
558 { 613 {
559 DifferentiatorInfo differentiator = cls.subclass_differentiator; 614 DifferentiatorInfo differentiator = cls.subclass_differentiator;
560 if (differentiator.offset != SIZE_MAX) 615 if (differentiator.offset != SIZE_MAX)
561 { 616 {
562 printf("var %s_mapping = \n", cls.name.c_str()); 617 printf("var %s_mapping = \n", cls.name.c_str());
563 puts("{"); 618 puts("{");
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
662 717
663 template<typename ClassType, 718 template<typename ClassType,
664 typename BaseClass = bindings_internal::NoBaseClass, 719 typename BaseClass = bindings_internal::NoBaseClass,
665 typename std::enable_if<std::is_base_of<ref_counted, ClassType>::value>::typ e* = nullptr> 720 typename std::enable_if<std::is_base_of<ref_counted, ClassType>::value>::typ e* = nullptr>
666 class class_ 721 class class_
667 { 722 {
668 public: 723 public:
669 class_(const char* name) 724 class_(const char* name)
670 { 725 {
671 ClassType* ptr = reinterpret_cast<ClassType*>(0x10000000); 726 ClassType* ptr = reinterpret_cast<ClassType*>(0x10000000);
672 int ref_counted_offset = 727 ptrdiff_t ref_counted_offset =
673 reinterpret_cast<int>(dynamic_cast<ref_counted*>(ptr)) - 728 reinterpret_cast<char*>(static_cast<ref_counted*>(ptr)) -
674 reinterpret_cast<int>(ptr); 729 reinterpret_cast<char*>(ptr);
675 bindings_internal::register_class(name, 730 bindings_internal::register_class(name,
676 bindings_internal::TypeInfo<ClassType>(), 731 bindings_internal::TypeInfo<ClassType>(),
677 bindings_internal::TypeInfo<BaseClass>(), 732 bindings_internal::TypeInfo<BaseClass>(),
678 ref_counted_offset 733 ref_counted_offset
679 ); 734 );
680 } 735 }
681 736
682 template<typename FieldType> 737 template<typename FieldType>
683 const class_& property(const char* name, 738 const class_& property(const char* name,
684 FieldType (ClassType::*getter)() const, 739 FieldType (ClassType::*getter)() const,
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 795
741 std::vector<std::pair<int, std::string>> mapping; 796 std::vector<std::pair<int, std::string>> mapping;
742 for (const auto& item : list) 797 for (const auto& item : list)
743 mapping.emplace_back(item.first, item.second); 798 mapping.emplace_back(item.first, item.second);
744 799
745 bindings_internal::register_differentiator( 800 bindings_internal::register_differentiator(
746 bindings_internal::TypeInfo<ClassType>(), offset, mapping); 801 bindings_internal::TypeInfo<ClassType>(), offset, mapping);
747 return *this; 802 return *this;
748 } 803 }
749 }; 804 };
LEFTRIGHT

Powered by Google App Engine
This is Rietveld