SlideShare uma empresa Scribd logo
1 de 76
Connecting C++ and JavaScript on 
the Web with Embind 
IMVU Inc. 
@chadaustin
Agenda 
• Why IMVU selected Emscripten 
– and thus wrote Embind 
• Overview of Embind’s features 
• C++11 tricks in the Embind implementation 
– code size 
– syntax 
• Please hold questions until the end
What is IMVU? 
• Avatars 
• Chatting 
• Games
What is IMVU? 
• 130 million registered accounts 
• 16 million user-generated virtual items
Why Emscripten?
Emscripten 
• Compiles C++ into JavaScript 
• asm.js has ~50% of native performance 
• No download or plugins! 
• Portable across Windows, Mac, Linux, 
Mobile, Tablets 
• C++: high-performance language on ALL 
platforms, including web
Emscripten!
asm.js 
• Statically-compilable, 
• Machine-language-translatable, 
• Typed, 
• Garbage-collection-free, 
• Subset of JavaScript
asm.js 
• Integer arithmetic mapped to JS operators 
• Heap represented as one ArrayBuffer 
– 8 TypedArrayViews alias into that buffer: 
• {signed, unsigned} {8, 16, 32} bit integers 
• 32- and 64-bit floats 
– See Alon’s presentation and 
engineering.imvu.com for more details
asm.js example 
// C++ 
void increment(unsigned* p) { 
++(*p); 
} 
// JavaScript 
function _increment(p) { 
p = p | 0; // p is an unsigned integer 
HEAPU32[p>>2] = (HEAPU32[p>>2] + 1) | 0; 
}
Emscripten 
• Compiling C++ into JS is just half of the 
platform 
• Implementations of many POSIX functions 
• Some hand-rolled APIs to access browser 
capabilities from C++ 
– setTimeout() 
– eval()
Browser Integration 
• JavaScript 
setTimeout(function() { 
… 
}, 1000); 
• Emscripten 
emscripten_async_call([](void* arg) { 
… 
}, arg, 1000);
Web Applications Want C++ 
• High-performance C++ components 
• Existing C++ libraries
From a high level 
EMBIND
Embind 
• C++ ⇔ JavaScript binding API 
• Bidirectional! 
• Inspired by Boost.Python 
• Included with Emscripten 
• Heavy use of C++11 features 
– variadic templates 
– constexpr 
– <type_traits>
Boost.Python 
• Almost every project I’ve worked on in the last 
decade has used Boost.Python 
• Some things I’ve never liked about 
Boost.Python 
– Significant C++ <-> Python call overhead 
– Huge generated code size 
– Huge compile times 
– Too much is implicit (e.g. automatic copy 
constructors)
Embind Design Spirit 
• Bindings written in C++ 
– no custom build step 
• Using JavaScript terminology 
• Minimal runtime overhead 
– generates high-performance glue code at runtime 
• Short, concise implementation
BINDING C++ TO JAVASCRIPT
Example 
EMSCRIPTEN_BINDINGS(foo_library) { 
function(“foo”, &foo); 
class_<C>(“C”) 
.constructor<int, std::string>() 
.function(“method”, &C::method) 
; 
}
Features 
• classes 
– member functions 
– ES5 properties 
– raw pointer ownership 
– smart pointer ownership 
• enums (both enum and enum class) 
• named arbitrary constant values 
• JavaScript extending C++ classes 
• overloading by argument count (not type)
ES5 Properties 
struct Character { 
int health = 100; 
void setHealth(int p) { health = p; } 
int getHealth() const { return health; } 
}; 
class_<Character>(“Character”) 
.constructor<>() 
.property(“health”, 
&Character::getHealth, 
&Character::setHealth) 
;
Enums 
enum Color { RED, GREEN, BLUE }; 
enum_<Color>(“Color”) 
.value(“RED”, RED) 
.value(“GREEN”, GREEN) 
.value(“BLUE”, BLUE) 
;
Constants 
constant( 
“DIAMETER_OF_EARTH”, 
DIAMETER_OF_EARTH);
Memory Management 
• JavaScript has NO weak pointers or GC 
callbacks 
• Manual memory management of C++ objects 
from JavaScript 
– simple refcounting support provided
Memory Management 
struct Point { int x, y; }; 
Point makePoint(int x, int y); 
class_<Point>(“Point”) 
.property(“x”, &Point::x) 
.property(“y”, &Point::y) 
; 
function(“makePoint”, &makePoint);
Memory Management 
> var p = makePoint(10, 20); 
> console.log(p.x); 
10 
> console.log(p); 
[Object] 
> p.delete(); // 
Memory Management (con’t) 
• “value types” 
– by-value conversion between C++ types and 
JavaScript Objects 
• {x: 10, y: 20} 
– conversion between C++ types and JavaScript 
Arrays 
• [10, 20]
Value Objects Example 
// C++ 
value_object<Point>(“Point”) 
.field(“x”, &Point::x) 
.field(“y”, &Point::y) 
; 
// JS 
var p = makePoint(10, 20); 
console.log(p); 
// {x: 10, y: 20} 
// no need to delete
USING JAVASCRIPT FROM C++
Calling JS from C++ 
• emscripten::val 
• allows manipulation of JS values from C++ 
// JavaScript 
var now = Date.now(); 
// C++ 
double now = val::global(“Date”).call<double>(“now”);
Using Web Audio from C++ 
#include <emscripten/val.h> 
using namespace emscripten; 
int main() { 
val context = val::global("AudioContext").new_(); // new AudioContext() 
val oscillator = context.call<val>("createOscillator"); 
oscillator.set("type", val("triangle")); // oscillator.type = “triangle” 
oscillator["frequency"].set("value", val(262)) // oscillator.frequency.value = 262 
oscillator.call<void>("connect", context["destination"]); 
oscillator.call<void>("start", 0); 
}
IMPLEMENTATION
Type IDs & Wire Types 
• Every C++ type has a Type ID 
• Type IDs have a name 
• Every C++ type has a corresponding Wire 
Type 
– C++ can produce a Wire Type for any value 
– JS can produce a Wire Type
Wire Types 
C++ Type Wire Type JavaScript Type 
int int Number 
char char Number 
double double Number 
std::string struct { size_t, char[] }* String 
std::wstring struct { size_t, wchar_t[] }* String 
emscripten::val _EM_VAL* arbitrary value 
class T T* Embind Handle
Function Binding 
float add2(float x, float y) { return x + y; } 
EMSCRIPTEN_BINDINGS(one_function) { 
function(“add2”, &add2); 
} 
// Notify embind of name, signature, and fp
Function Binding (con’t) 
void _embind_register_function( 
const char* name, 
unsigned argCount, 
const TYPEID argTypes[], 
const char* signature, 
GenericFunction invoker, 
GenericFunction function);
Function Binding Under The Covers 
function("add2", &add2); 
// becomes 
TYPEID argTypes[3] = {getTypeID<float>(), getTypeID<float>(), getTypeID<float>()}; 
_embind_register_function( 
"add2”, 
3, 
argTypes, 
"fff”, 
&Invoker<float, float, float>, 
&add2);
Function Binding (con’t) 
_embind_register_function: function(name, argCount, rawArgTypesAddr, signature, rawInvoker, 
fn) { 
var argTypes = heap32VectorToArray(argCount, rawArgTypesAddr); 
name = readLatin1String(name); 
rawInvoker = requireFunction(signature, rawInvoker); 
exposePublicSymbol(name, function() { 
throwUnboundTypeError('Cannot call ' + name + ' due to unbound types', argTypes); 
}, argCount - 1); 
whenDependentTypesAreResolved([], argTypes, function(argTypes) { 
var invokerArgsArray = [argTypes[0], null].concat(argTypes.slice(1)); 
replacePublicSymbol(name, craftInvokerFunction(name, invokerArgsArray, null, rawInvoker, 
fn), argCount - 1); 
return []; 
}); 
},
C++ TECHNIQUES AND TRICKS
C++ Techniques and Tricks 
• Code Size 
– Using static constexpr to create static arrays 
– RTTI Light 
• Syntax 
– select_overload 
– optional_override
Why is code size so important? 
• Native Application 
– mmap .exe on disk 
– begin executing functions 
– page in instructions on demand 
• JavaScript Application 
– download JavaScript 
– parse 
– codegen on user’s machine 
– execute JavaScript, maybe JIT on the fly
STATIC ARRAYS
Function Binding (con’t) 
• name 
– “add2” 
• signature 
– 3 (1 return value, 2 arguments) 
– argTypes = {FLOAT, FLOAT, FLOAT} 
– asm.js signature string: “fff” 
– invoker = arg reconstruction from wiretype 
• function pointer
Signatures 
• Signatures are known at compile-time 
• Signatures are constant 
• Often reused 
– e.g. float operator+, float operator*, and powf 
• constexpr!
asm.js Signature Strings 
• asm.js function table signature strings 
• <void, float, int, char*>  “vfii” 
• Wanted: compile-time string literal 
generation
SignatureCode 
template<typename T> struct SignatureCode { 
static constexpr char get() { return 'i'; } 
}; 
template<> struct SignatureCode<void> { 
static constexpr char get() { return 'v'; } 
}; 
template<> struct SignatureCode<float> { 
static constexpr char get() { return 'f'; } 
}; 
template<> struct SignatureCode<double> { 
static constexpr char get() { return 'd'; } 
};
getSignature 
template<typename Return, typename... Args> 
const char* getSignature(Return (*)(Args...)) { 
static constexpr char str[] = { 
SignatureCode<Return>::get(), 
SignatureCode<Args>::get()..., 
0 }; 
return str; 
}
RTTI LIGHT
RTTI Light 
void _embind_register_function( 
const char* name, 
unsigned argCount, 
const TYPEID argTypes[], 
const char* signature, 
GenericFunction invoker, 
GenericFunction function); 
• TYPEID is an integer or void* that identifies the type 
• Used as index into type registry
Original TYPEID Implementation 
• Originally used typeid() 
• typedef const std::type_info* TYPEID; 
• Problem: code size!
Problems with typeid 
• typeid pulls in a lot of extra junk 
– e.g. long string constants for mangled names 
• Embind already associates human names with every 
type, typeid name is only necessary for errors 
– “Error: tried to call function X but argument 2 has unbound 
type Y” 
– Errors only used for debugging 
– #define EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES 0
RTTI Light Requirements 
• All embind needs, per type, is: 
– unique word-sized identifier per type 
– unique string name 
• Lookup should constexpr (we’ll see why later) 
• Important: still need full RTTI for runtime 
identification of polymorphic pointers! 
• LightTypeID must inhabit the same namespace 
as typeid to avoid namespace collisions
TYPEID lookup 
typedef const void* TYPEID; 
template<typename T> 
static constexpr TYPEID getLightTypeID() { 
return std::is_polymorphic<T>::value 
? &typeid(C) 
: LightTypeID<C>::get(); 
}
LightTypeID 
template<typename T> 
struct LightTypeID { 
static char c; 
static constexpr TYPEID get() { 
return &c; 
} 
}; 
// Warning: how does linkage work here? 
template<typename T> 
char LightTypeID<T>::c;
RTTI Light 
• Allocates a single byte in the static data 
segment per type, uses its address 
• Same namespace as typeid 
• Huge code size savings! 
• 175 KB off of our minified JavaScript build
Signature TYPEID[] 
template<typename… Args> 
static const TYPEID* getTypeIDs() { 
static constexpr TYPEID types[] = { 
TypeID<Args>::get()… 
}; 
return types; 
}
Back to Function Registration 
_embind_register_function( 
50001482, // address of “add2” 
3, // argCount=3 
50001830, // address of TYPEID[3] 
50001497, // address of “fff” 
106, // function pointer of invoker 
80); // function pointer of add2
SELECT_OVERLOAD
select_overload 
• Want to bind overloaded function e.g. pow() 
// ambiguous: pow is overloaded 
function(“pow”, &pow); 
• You can C-style cast to select the function signature 
function(“powf”, (float(*)(float,float))&pow); 
function(“powd”, (double(*)(double,double))&pow);
C-style casts are gross 
• Ugly (*) sigil 
• Dangerous when function is refactored to 
not be overloaded 
– C-style cast will still succeed! 
– Undefined behavior
Better Way 
function(“powf”, 
select_overload<float(float,float)>(&pow)); 
function(“powd”, 
select_overload<double(double,double)>(&pow));
select_overload Implementation 
template<typename Signature> 
Signature* select_overload(Signature* fn) { 
return fn; 
}
select_overload on Member Functions 
struct HasProperty { 
int prop(); 
void prop(int); 
};
The Old Way 
• C-style casting requires duplicating class name 
class_<HasProperty>(“HasProperty”) 
.method(“prop”, 
(int(HasProperty::*)())&HasProperty::prop) 
.method(“prop”, 
(void(HasProperty::*)(int))&HasProperty::prop) 
;
Using select_overload 
class_<HasProperty>(“HasProperty”) 
.method(“prop”, select_overload<int()>( 
&HasProperty::prop)) 
.method(“prop”, select_overload<void(int)>( 
&HasProperty::prop)) 
; 
• Does not repeat class name
select_overload Implementation 
template< 
typename Signature, 
typename ClassType> 
auto select_overload( 
Signature (ClassType::*fn) 
) -> decltype(fn) { 
return fn; 
}
aka deducing signature of captureless lambda 
OPTIONAL_OVERRIDE
optional_override in use 
struct Base { 
virtual void invoke(const std::string& str) { 
// default implementation 
} 
}; 
class_<Base>("Base") 
.allow_subclass<BaseWrapper>() 
.function("invoke", optional_override([](Base& self, const std::string& str) { 
return self.Base::invoke(str); 
})) 
;
optional_override 
• Sometimes you want to bind a captureless 
lambda 
– Use case is too subtle for discussion here 
– Captureless lambdas can be coerced into C 
function pointers 
• But what’s a lambda’s signature?
Lambdas are Sugar for Objects with 
Call Operators 
[](int a) { return a + 2; } 
// desugars to 
struct __AnonymousLambda { 
int operator()(int a) { return __body(a); } 
typedef int(*__FP)(int); 
operator __FP() { return &__body; } 
private: 
static int __body(int a) { return a + 2; } 
}; 
• We want type of function pointer: int(*)(int) in this case
optional_override Implementation 
// this should be in <type_traits>, but alas, it's not 
template<typename T> struct remove_class; 
template<typename C, typename R, typename... A> 
struct remove_class<R(C::*)(A...)> { using type = R(A...); }; 
template<typename C, typename R, typename... A> 
struct remove_class<R(C::*)(A...) const> { using type = R(A...); }; 
template<typename C, typename R, typename... A> 
struct remove_class<R(C::*)(A...) volatile> { using type = R(A...); }; 
template<typename C, typename R, typename... A> 
struct remove_class<R(C::*)(A...) const volatile> { using type = R(A...); };
optional_override Implementation 
template<typename LambdaType> 
using LambdaSignature = 
typename remove_class< 
decltype(&LambdaType::operator()) 
>::type;
optional_override Implementation 
template<typename LambdaType> 
LambdaSignature<LambdaType>* 
optional_override(const LambdaType& fp) { 
return fp; 
}
WHEW…
Overview 
• C++ has bright future on the web 
• C++ libraries now available to JavaScript 
• C++ can call JavaScript code 
• Low-overhead: 200 ns overhead per call 
– more optimizations possible! 
• Emphasis on small generated code size 
• Without C++11, writing embind would have been 
really annoying 
• Hope you learned a few tricks!
We’re Hiring! 
Questions? 
@chadaustin 
chad@imvu.com 
http://emscripten.org/

Mais conteúdo relacionado

Mais procurados

Z Buffer Optimizations
Z Buffer OptimizationsZ Buffer Optimizations
Z Buffer Optimizations
pjcozzi
 

Mais procurados (20)

Low-level Shader Optimization for Next-Gen and DX11 by Emil Persson
Low-level Shader Optimization for Next-Gen and DX11 by Emil PerssonLow-level Shader Optimization for Next-Gen and DX11 by Emil Persson
Low-level Shader Optimization for Next-Gen and DX11 by Emil Persson
 
Choi JiHyun NDC2011
Choi JiHyun  NDC2011Choi JiHyun  NDC2011
Choi JiHyun NDC2011
 
CryENGINE 3 Rendering Techniques
CryENGINE 3 Rendering TechniquesCryENGINE 3 Rendering Techniques
CryENGINE 3 Rendering Techniques
 
Bending the Graphics Pipeline
Bending the Graphics PipelineBending the Graphics Pipeline
Bending the Graphics Pipeline
 
Optimizing the Graphics Pipeline with Compute, GDC 2016
Optimizing the Graphics Pipeline with Compute, GDC 2016Optimizing the Graphics Pipeline with Compute, GDC 2016
Optimizing the Graphics Pipeline with Compute, GDC 2016
 
HDR Theory and practicce (JP)
HDR Theory and practicce (JP)HDR Theory and practicce (JP)
HDR Theory and practicce (JP)
 
아티스트에게 사랑받는 3DS Max 우버쉐이더
아티스트에게 사랑받는 3DS Max 우버쉐이더아티스트에게 사랑받는 3DS Max 우버쉐이더
아티스트에게 사랑받는 3DS Max 우버쉐이더
 
Z Buffer Optimizations
Z Buffer OptimizationsZ Buffer Optimizations
Z Buffer Optimizations
 
Five Rendering Ideas from Battlefield 3 & Need For Speed: The Run
Five Rendering Ideas from Battlefield 3 & Need For Speed: The RunFive Rendering Ideas from Battlefield 3 & Need For Speed: The Run
Five Rendering Ideas from Battlefield 3 & Need For Speed: The Run
 
Ndc12 이창희 render_pipeline
Ndc12 이창희 render_pipelineNdc12 이창희 render_pipeline
Ndc12 이창희 render_pipeline
 
The Unique Lighting of Mirror's Edge
The Unique Lighting of Mirror's EdgeThe Unique Lighting of Mirror's Edge
The Unique Lighting of Mirror's Edge
 
Terrain in Battlefield 3: A Modern, Complete and Scalable System
Terrain in Battlefield 3: A Modern, Complete and Scalable SystemTerrain in Battlefield 3: A Modern, Complete and Scalable System
Terrain in Battlefield 3: A Modern, Complete and Scalable System
 
Dynamic Resolution and Interlaced Rendering
Dynamic Resolution and Interlaced RenderingDynamic Resolution and Interlaced Rendering
Dynamic Resolution and Interlaced Rendering
 
Rendering Tech of Space Marine
Rendering Tech of Space MarineRendering Tech of Space Marine
Rendering Tech of Space Marine
 
CEDEC 2018 - Towards Effortless Photorealism Through Real-Time Raytracing
CEDEC 2018 - Towards Effortless Photorealism Through Real-Time RaytracingCEDEC 2018 - Towards Effortless Photorealism Through Real-Time Raytracing
CEDEC 2018 - Towards Effortless Photorealism Through Real-Time Raytracing
 
CS 354 Transformation, Clipping, and Culling
CS 354 Transformation, Clipping, and CullingCS 354 Transformation, Clipping, and Culling
CS 354 Transformation, Clipping, and Culling
 
[NDC17] 물리 기반 대기와 구름 만들기
[NDC17] 물리 기반 대기와 구름 만들기[NDC17] 물리 기반 대기와 구름 만들기
[NDC17] 물리 기반 대기와 구름 만들기
 
Crysis 2-key-rendering-features
Crysis 2-key-rendering-featuresCrysis 2-key-rendering-features
Crysis 2-key-rendering-features
 
Graphics Gems from CryENGINE 3 (Siggraph 2013)
Graphics Gems from CryENGINE 3 (Siggraph 2013)Graphics Gems from CryENGINE 3 (Siggraph 2013)
Graphics Gems from CryENGINE 3 (Siggraph 2013)
 
Screen Space Reflections in The Surge
Screen Space Reflections in The SurgeScreen Space Reflections in The Surge
Screen Space Reflections in The Surge
 

Semelhante a Connecting C++ and JavaScript on the Web with Embind

Auto cad 2006_api_overview
Auto cad 2006_api_overviewAuto cad 2006_api_overview
Auto cad 2006_api_overview
scdhruv5
 
JSLounge - TypeScript 소개
JSLounge - TypeScript 소개JSLounge - TypeScript 소개
JSLounge - TypeScript 소개
Reagan Hwang
 
[Td 2015] what is new in visual c++ 2015 and future directions(ulzii luvsanba...
[Td 2015] what is new in visual c++ 2015 and future directions(ulzii luvsanba...[Td 2015] what is new in visual c++ 2015 and future directions(ulzii luvsanba...
[Td 2015] what is new in visual c++ 2015 and future directions(ulzii luvsanba...
Sang Don Kim
 
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
jeffz
 
Cs1123 11 pointers
Cs1123 11 pointersCs1123 11 pointers
Cs1123 11 pointers
TAlha MAlik
 
Jslab rssh: JS as language platform
Jslab rssh:  JS as language platformJslab rssh:  JS as language platform
Jslab rssh: JS as language platform
Ruslan Shevchenko
 
Dr archana dhawan bajaj - c# dot net
Dr archana dhawan bajaj - c# dot netDr archana dhawan bajaj - c# dot net
Dr archana dhawan bajaj - c# dot net
Dr-archana-dhawan-bajaj
 
Abhishek lingineni
Abhishek lingineniAbhishek lingineni
Abhishek lingineni
abhishekl404
 

Semelhante a Connecting C++ and JavaScript on the Web with Embind (20)

Auto cad 2006_api_overview
Auto cad 2006_api_overviewAuto cad 2006_api_overview
Auto cad 2006_api_overview
 
C++ L01-Variables
C++ L01-VariablesC++ L01-Variables
C++ L01-Variables
 
JSLounge - TypeScript 소개
JSLounge - TypeScript 소개JSLounge - TypeScript 소개
JSLounge - TypeScript 소개
 
CGI.ppt
CGI.pptCGI.ppt
CGI.ppt
 
TypeScript: Angular's Secret Weapon
TypeScript: Angular's Secret WeaponTypeScript: Angular's Secret Weapon
TypeScript: Angular's Secret Weapon
 
Modern C++
Modern C++Modern C++
Modern C++
 
TypeScript: Angular's Secret Weapon
TypeScript: Angular's Secret WeaponTypeScript: Angular's Secret Weapon
TypeScript: Angular's Secret Weapon
 
Skiron - Experiments in CPU Design in D
Skiron - Experiments in CPU Design in DSkiron - Experiments in CPU Design in D
Skiron - Experiments in CPU Design in D
 
Introduction to c#
Introduction to c#Introduction to c#
Introduction to c#
 
[Td 2015] what is new in visual c++ 2015 and future directions(ulzii luvsanba...
[Td 2015] what is new in visual c++ 2015 and future directions(ulzii luvsanba...[Td 2015] what is new in visual c++ 2015 and future directions(ulzii luvsanba...
[Td 2015] what is new in visual c++ 2015 and future directions(ulzii luvsanba...
 
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)The Evolution of Async-Programming on .NET Platform (.Net China, C#)
The Evolution of Async-Programming on .NET Platform (.Net China, C#)
 
Cs1123 11 pointers
Cs1123 11 pointersCs1123 11 pointers
Cs1123 11 pointers
 
Rider - Taking ReSharper out of Process
Rider - Taking ReSharper out of ProcessRider - Taking ReSharper out of Process
Rider - Taking ReSharper out of Process
 
C# 7.x What's new and what's coming with C# 8
C# 7.x What's new and what's coming with C# 8C# 7.x What's new and what's coming with C# 8
C# 7.x What's new and what's coming with C# 8
 
JSLab.Руслан Шевченко."JavaScript как платформа компиляции"
JSLab.Руслан Шевченко."JavaScript как платформа компиляции"JSLab.Руслан Шевченко."JavaScript как платформа компиляции"
JSLab.Руслан Шевченко."JavaScript как платформа компиляции"
 
Jslab rssh: JS as language platform
Jslab rssh:  JS as language platformJslab rssh:  JS as language platform
Jslab rssh: JS as language platform
 
Angular2 for Beginners
Angular2 for BeginnersAngular2 for Beginners
Angular2 for Beginners
 
Java Jit. Compilation and optimization by Andrey Kovalenko
Java Jit. Compilation and optimization by Andrey KovalenkoJava Jit. Compilation and optimization by Andrey Kovalenko
Java Jit. Compilation and optimization by Andrey Kovalenko
 
Dr archana dhawan bajaj - c# dot net
Dr archana dhawan bajaj - c# dot netDr archana dhawan bajaj - c# dot net
Dr archana dhawan bajaj - c# dot net
 
Abhishek lingineni
Abhishek lingineniAbhishek lingineni
Abhishek lingineni
 

Último

CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

Último (20)

08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 

Connecting C++ and JavaScript on the Web with Embind

  • 1. Connecting C++ and JavaScript on the Web with Embind IMVU Inc. @chadaustin
  • 2. Agenda • Why IMVU selected Emscripten – and thus wrote Embind • Overview of Embind’s features • C++11 tricks in the Embind implementation – code size – syntax • Please hold questions until the end
  • 3. What is IMVU? • Avatars • Chatting • Games
  • 4. What is IMVU? • 130 million registered accounts • 16 million user-generated virtual items
  • 6. Emscripten • Compiles C++ into JavaScript • asm.js has ~50% of native performance • No download or plugins! • Portable across Windows, Mac, Linux, Mobile, Tablets • C++: high-performance language on ALL platforms, including web
  • 8. asm.js • Statically-compilable, • Machine-language-translatable, • Typed, • Garbage-collection-free, • Subset of JavaScript
  • 9. asm.js • Integer arithmetic mapped to JS operators • Heap represented as one ArrayBuffer – 8 TypedArrayViews alias into that buffer: • {signed, unsigned} {8, 16, 32} bit integers • 32- and 64-bit floats – See Alon’s presentation and engineering.imvu.com for more details
  • 10. asm.js example // C++ void increment(unsigned* p) { ++(*p); } // JavaScript function _increment(p) { p = p | 0; // p is an unsigned integer HEAPU32[p>>2] = (HEAPU32[p>>2] + 1) | 0; }
  • 11. Emscripten • Compiling C++ into JS is just half of the platform • Implementations of many POSIX functions • Some hand-rolled APIs to access browser capabilities from C++ – setTimeout() – eval()
  • 12. Browser Integration • JavaScript setTimeout(function() { … }, 1000); • Emscripten emscripten_async_call([](void* arg) { … }, arg, 1000);
  • 13. Web Applications Want C++ • High-performance C++ components • Existing C++ libraries
  • 14. From a high level EMBIND
  • 15. Embind • C++ ⇔ JavaScript binding API • Bidirectional! • Inspired by Boost.Python • Included with Emscripten • Heavy use of C++11 features – variadic templates – constexpr – <type_traits>
  • 16. Boost.Python • Almost every project I’ve worked on in the last decade has used Boost.Python • Some things I’ve never liked about Boost.Python – Significant C++ <-> Python call overhead – Huge generated code size – Huge compile times – Too much is implicit (e.g. automatic copy constructors)
  • 17. Embind Design Spirit • Bindings written in C++ – no custom build step • Using JavaScript terminology • Minimal runtime overhead – generates high-performance glue code at runtime • Short, concise implementation
  • 18. BINDING C++ TO JAVASCRIPT
  • 19. Example EMSCRIPTEN_BINDINGS(foo_library) { function(“foo”, &foo); class_<C>(“C”) .constructor<int, std::string>() .function(“method”, &C::method) ; }
  • 20. Features • classes – member functions – ES5 properties – raw pointer ownership – smart pointer ownership • enums (both enum and enum class) • named arbitrary constant values • JavaScript extending C++ classes • overloading by argument count (not type)
  • 21. ES5 Properties struct Character { int health = 100; void setHealth(int p) { health = p; } int getHealth() const { return health; } }; class_<Character>(“Character”) .constructor<>() .property(“health”, &Character::getHealth, &Character::setHealth) ;
  • 22. Enums enum Color { RED, GREEN, BLUE }; enum_<Color>(“Color”) .value(“RED”, RED) .value(“GREEN”, GREEN) .value(“BLUE”, BLUE) ;
  • 24. Memory Management • JavaScript has NO weak pointers or GC callbacks • Manual memory management of C++ objects from JavaScript – simple refcounting support provided
  • 25. Memory Management struct Point { int x, y; }; Point makePoint(int x, int y); class_<Point>(“Point”) .property(“x”, &Point::x) .property(“y”, &Point::y) ; function(“makePoint”, &makePoint);
  • 26. Memory Management > var p = makePoint(10, 20); > console.log(p.x); 10 > console.log(p); [Object] > p.delete(); // 
  • 27. Memory Management (con’t) • “value types” – by-value conversion between C++ types and JavaScript Objects • {x: 10, y: 20} – conversion between C++ types and JavaScript Arrays • [10, 20]
  • 28. Value Objects Example // C++ value_object<Point>(“Point”) .field(“x”, &Point::x) .field(“y”, &Point::y) ; // JS var p = makePoint(10, 20); console.log(p); // {x: 10, y: 20} // no need to delete
  • 30. Calling JS from C++ • emscripten::val • allows manipulation of JS values from C++ // JavaScript var now = Date.now(); // C++ double now = val::global(“Date”).call<double>(“now”);
  • 31. Using Web Audio from C++ #include <emscripten/val.h> using namespace emscripten; int main() { val context = val::global("AudioContext").new_(); // new AudioContext() val oscillator = context.call<val>("createOscillator"); oscillator.set("type", val("triangle")); // oscillator.type = “triangle” oscillator["frequency"].set("value", val(262)) // oscillator.frequency.value = 262 oscillator.call<void>("connect", context["destination"]); oscillator.call<void>("start", 0); }
  • 33. Type IDs & Wire Types • Every C++ type has a Type ID • Type IDs have a name • Every C++ type has a corresponding Wire Type – C++ can produce a Wire Type for any value – JS can produce a Wire Type
  • 34. Wire Types C++ Type Wire Type JavaScript Type int int Number char char Number double double Number std::string struct { size_t, char[] }* String std::wstring struct { size_t, wchar_t[] }* String emscripten::val _EM_VAL* arbitrary value class T T* Embind Handle
  • 35. Function Binding float add2(float x, float y) { return x + y; } EMSCRIPTEN_BINDINGS(one_function) { function(“add2”, &add2); } // Notify embind of name, signature, and fp
  • 36. Function Binding (con’t) void _embind_register_function( const char* name, unsigned argCount, const TYPEID argTypes[], const char* signature, GenericFunction invoker, GenericFunction function);
  • 37. Function Binding Under The Covers function("add2", &add2); // becomes TYPEID argTypes[3] = {getTypeID<float>(), getTypeID<float>(), getTypeID<float>()}; _embind_register_function( "add2”, 3, argTypes, "fff”, &Invoker<float, float, float>, &add2);
  • 38. Function Binding (con’t) _embind_register_function: function(name, argCount, rawArgTypesAddr, signature, rawInvoker, fn) { var argTypes = heap32VectorToArray(argCount, rawArgTypesAddr); name = readLatin1String(name); rawInvoker = requireFunction(signature, rawInvoker); exposePublicSymbol(name, function() { throwUnboundTypeError('Cannot call ' + name + ' due to unbound types', argTypes); }, argCount - 1); whenDependentTypesAreResolved([], argTypes, function(argTypes) { var invokerArgsArray = [argTypes[0], null].concat(argTypes.slice(1)); replacePublicSymbol(name, craftInvokerFunction(name, invokerArgsArray, null, rawInvoker, fn), argCount - 1); return []; }); },
  • 40. C++ Techniques and Tricks • Code Size – Using static constexpr to create static arrays – RTTI Light • Syntax – select_overload – optional_override
  • 41. Why is code size so important? • Native Application – mmap .exe on disk – begin executing functions – page in instructions on demand • JavaScript Application – download JavaScript – parse – codegen on user’s machine – execute JavaScript, maybe JIT on the fly
  • 43. Function Binding (con’t) • name – “add2” • signature – 3 (1 return value, 2 arguments) – argTypes = {FLOAT, FLOAT, FLOAT} – asm.js signature string: “fff” – invoker = arg reconstruction from wiretype • function pointer
  • 44. Signatures • Signatures are known at compile-time • Signatures are constant • Often reused – e.g. float operator+, float operator*, and powf • constexpr!
  • 45. asm.js Signature Strings • asm.js function table signature strings • <void, float, int, char*>  “vfii” • Wanted: compile-time string literal generation
  • 46. SignatureCode template<typename T> struct SignatureCode { static constexpr char get() { return 'i'; } }; template<> struct SignatureCode<void> { static constexpr char get() { return 'v'; } }; template<> struct SignatureCode<float> { static constexpr char get() { return 'f'; } }; template<> struct SignatureCode<double> { static constexpr char get() { return 'd'; } };
  • 47. getSignature template<typename Return, typename... Args> const char* getSignature(Return (*)(Args...)) { static constexpr char str[] = { SignatureCode<Return>::get(), SignatureCode<Args>::get()..., 0 }; return str; }
  • 49. RTTI Light void _embind_register_function( const char* name, unsigned argCount, const TYPEID argTypes[], const char* signature, GenericFunction invoker, GenericFunction function); • TYPEID is an integer or void* that identifies the type • Used as index into type registry
  • 50. Original TYPEID Implementation • Originally used typeid() • typedef const std::type_info* TYPEID; • Problem: code size!
  • 51. Problems with typeid • typeid pulls in a lot of extra junk – e.g. long string constants for mangled names • Embind already associates human names with every type, typeid name is only necessary for errors – “Error: tried to call function X but argument 2 has unbound type Y” – Errors only used for debugging – #define EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES 0
  • 52. RTTI Light Requirements • All embind needs, per type, is: – unique word-sized identifier per type – unique string name • Lookup should constexpr (we’ll see why later) • Important: still need full RTTI for runtime identification of polymorphic pointers! • LightTypeID must inhabit the same namespace as typeid to avoid namespace collisions
  • 53. TYPEID lookup typedef const void* TYPEID; template<typename T> static constexpr TYPEID getLightTypeID() { return std::is_polymorphic<T>::value ? &typeid(C) : LightTypeID<C>::get(); }
  • 54. LightTypeID template<typename T> struct LightTypeID { static char c; static constexpr TYPEID get() { return &c; } }; // Warning: how does linkage work here? template<typename T> char LightTypeID<T>::c;
  • 55. RTTI Light • Allocates a single byte in the static data segment per type, uses its address • Same namespace as typeid • Huge code size savings! • 175 KB off of our minified JavaScript build
  • 56. Signature TYPEID[] template<typename… Args> static const TYPEID* getTypeIDs() { static constexpr TYPEID types[] = { TypeID<Args>::get()… }; return types; }
  • 57. Back to Function Registration _embind_register_function( 50001482, // address of “add2” 3, // argCount=3 50001830, // address of TYPEID[3] 50001497, // address of “fff” 106, // function pointer of invoker 80); // function pointer of add2
  • 59. select_overload • Want to bind overloaded function e.g. pow() // ambiguous: pow is overloaded function(“pow”, &pow); • You can C-style cast to select the function signature function(“powf”, (float(*)(float,float))&pow); function(“powd”, (double(*)(double,double))&pow);
  • 60. C-style casts are gross • Ugly (*) sigil • Dangerous when function is refactored to not be overloaded – C-style cast will still succeed! – Undefined behavior
  • 61. Better Way function(“powf”, select_overload<float(float,float)>(&pow)); function(“powd”, select_overload<double(double,double)>(&pow));
  • 62. select_overload Implementation template<typename Signature> Signature* select_overload(Signature* fn) { return fn; }
  • 63. select_overload on Member Functions struct HasProperty { int prop(); void prop(int); };
  • 64. The Old Way • C-style casting requires duplicating class name class_<HasProperty>(“HasProperty”) .method(“prop”, (int(HasProperty::*)())&HasProperty::prop) .method(“prop”, (void(HasProperty::*)(int))&HasProperty::prop) ;
  • 65. Using select_overload class_<HasProperty>(“HasProperty”) .method(“prop”, select_overload<int()>( &HasProperty::prop)) .method(“prop”, select_overload<void(int)>( &HasProperty::prop)) ; • Does not repeat class name
  • 66. select_overload Implementation template< typename Signature, typename ClassType> auto select_overload( Signature (ClassType::*fn) ) -> decltype(fn) { return fn; }
  • 67. aka deducing signature of captureless lambda OPTIONAL_OVERRIDE
  • 68. optional_override in use struct Base { virtual void invoke(const std::string& str) { // default implementation } }; class_<Base>("Base") .allow_subclass<BaseWrapper>() .function("invoke", optional_override([](Base& self, const std::string& str) { return self.Base::invoke(str); })) ;
  • 69. optional_override • Sometimes you want to bind a captureless lambda – Use case is too subtle for discussion here – Captureless lambdas can be coerced into C function pointers • But what’s a lambda’s signature?
  • 70. Lambdas are Sugar for Objects with Call Operators [](int a) { return a + 2; } // desugars to struct __AnonymousLambda { int operator()(int a) { return __body(a); } typedef int(*__FP)(int); operator __FP() { return &__body; } private: static int __body(int a) { return a + 2; } }; • We want type of function pointer: int(*)(int) in this case
  • 71. optional_override Implementation // this should be in <type_traits>, but alas, it's not template<typename T> struct remove_class; template<typename C, typename R, typename... A> struct remove_class<R(C::*)(A...)> { using type = R(A...); }; template<typename C, typename R, typename... A> struct remove_class<R(C::*)(A...) const> { using type = R(A...); }; template<typename C, typename R, typename... A> struct remove_class<R(C::*)(A...) volatile> { using type = R(A...); }; template<typename C, typename R, typename... A> struct remove_class<R(C::*)(A...) const volatile> { using type = R(A...); };
  • 72. optional_override Implementation template<typename LambdaType> using LambdaSignature = typename remove_class< decltype(&LambdaType::operator()) >::type;
  • 73. optional_override Implementation template<typename LambdaType> LambdaSignature<LambdaType>* optional_override(const LambdaType& fp) { return fp; }
  • 75. Overview • C++ has bright future on the web • C++ libraries now available to JavaScript • C++ can call JavaScript code • Low-overhead: 200 ns overhead per call – more optimizations possible! • Emphasis on small generated code size • Without C++11, writing embind would have been really annoying • Hope you learned a few tricks!
  • 76. We’re Hiring! Questions? @chadaustin chad@imvu.com http://emscripten.org/