Created
August 19, 2017 02:07
-
-
Save veryjos/8d6649e6fd24b482757b9a12d38aa4cc to your computer and use it in GitHub Desktop.
legacy currychakra example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "CC_Config.hpp" | |
using namespace CurryChakra; | |
// Shims for JS types | |
// JsValueRef | |
JsValueRef CppToJs(JsValueRef& value) { | |
return value; | |
}; | |
void JsToCpp(JsValueRef& obj, JsValueRef& value) { | |
obj = value; | |
}; | |
// Doubles | |
JsValueRef CppToJs(double& value) { | |
JsValueRef jsValue; | |
ExceptIfError(JsDoubleToNumber(value, &jsValue)); | |
return jsValue; | |
}; | |
void JsToCpp(double& obj, JsValueRef &jsValue) { | |
ExceptIfError(JsNumberToDouble(jsValue, &obj)); | |
}; | |
// Ints (implicitly doubles) | |
JsValueRef CppToJs(int& value) { | |
JsValueRef jsValue; | |
ExceptIfError(JsDoubleToNumber(value, &jsValue)); | |
return jsValue; | |
}; | |
void JsToCpp(int& obj, JsValueRef &jsValue) { | |
double v; | |
ExceptIfError(JsNumberToDouble(jsValue, &v)); | |
obj = v; | |
}; | |
JsValueRef CppToJs(unsigned int& value) { | |
JsValueRef jsValue; | |
ExceptIfError(JsDoubleToNumber(value, &jsValue)); | |
return jsValue; | |
}; | |
void JsToCpp(unsigned int& obj, JsValueRef &jsValue) { | |
double v; | |
ExceptIfError(JsNumberToDouble(jsValue, &v)); | |
obj = v; | |
}; | |
// Floats | |
JsValueRef CppToJs(float& value) { | |
JsValueRef jsValue; | |
ExceptIfError(JsDoubleToNumber(value, &jsValue)); | |
return jsValue; | |
}; | |
void JsToCpp(float& obj, JsValueRef &jsValue) { | |
double v; | |
ExceptIfError(JsNumberToDouble(jsValue, &v)); | |
obj = v; | |
}; | |
// Strings (only by copy) | |
JsValueRef CppToJs(std::string& value) { | |
JsValueRef jsValue; | |
ExceptIfError(JsCreateString(value.c_str(), value.length(), &jsValue)); | |
return jsValue; | |
}; | |
void JsToCpp(std::string& obj, JsValueRef& jsValue) { | |
obj = ch::ReadStdString(jsValue); | |
}; | |
// Vectors (only by copy) | |
template <typename T> | |
JsValueRef CppToJs(std::vector<T>& obj) { | |
JsValueRef arr; | |
ExceptIfError(JsCreateArray(obj.size(), &arr)); | |
for (uint32_t i=0;i<obj.size();++i) | |
ExceptIfError(JsSetIndexedProperty(arr, CppToJs(i), CppToJs(obj[i]))); | |
return arr; | |
}; | |
template <typename T> | |
void JsToCpp(std::vector<T>& obj, JsValueRef& arr) { | |
// Get the number of elements in the JS array | |
JsValueRef length; | |
ExceptIfError(ch::GetPropertyValueByName(arr, "length", &length)); | |
// Just in case the elements are ref counted, create a new vector and | |
// copy it into it. | |
std::vector<T> copy; | |
copy.reserve(obj.size()); | |
// Convert it to cpp | |
uint32_t num_elements; | |
JsToCpp(num_elements, length); | |
for (uint32_t i=0;i<num_elements;++i) { | |
// Get the JS element | |
JsValueRef jsElement; | |
JsGetIndexedProperty(arr, CppToJs(i), &jsElement); | |
// Copy each element over | |
T elementCopy; | |
JsToCpp(elementCopy, jsElement); | |
copy.push_back(elementCopy); | |
} | |
obj = copy; | |
}; | |
// End shims for JS types | |
// Shims for Vec2 | |
static JsValueRef __js_prototype_Vec2; | |
JsValueRef CppToJs(Vec2*& obj) { | |
JsValueRef jsValue = obj->GetCCHandle(); | |
if (!jsValue) { | |
CC_CppHandle<Vec2>* handle = new CC_CppHandle<Vec2>(obj); | |
ExceptIfError(JsCreateExternalObject(handle, nullptr/*finalizeCallback*/, &jsValue)); | |
ExceptIfError(JsSetPrototype(jsValue, __js_prototype_Vec2)); | |
obj->SetCCHandle(jsValue); | |
} | |
return jsValue; | |
}; | |
void JsToCpp(Vec2*& obj, JsValueRef& jsValue) { | |
CC_CppHandle<Vec2>* handle; | |
ExceptIfError(JsGetExternalData(jsValue, (void**)&handle)); | |
obj = handle->GetPointer(); | |
}; | |
JsValueRef CppToJs(Vec2& obj) { | |
// turn this cpp value into a js value by copy | |
Vec2* heapObj = new Vec2(obj); | |
CC_CppHandle<Vec2>* handle = new CC_CppHandle<Vec2>(new Vec2(obj)); | |
JsValueRef jsValue; | |
ExceptIfError(JsCreateExternalObject(handle, nullptr/*finalizeCallback*/, &jsValue)); | |
ExceptIfError(JsSetPrototype(jsValue, __js_prototype_Vec2)); | |
heapObj->SetCCHandle(jsValue); | |
return jsValue; | |
}; | |
JsValueRef CppToJs(std::shared_ptr<Vec2>& obj) { | |
std::shared_ptr<Vec2> heapObj = std::shared_ptr<Vec2>(obj); | |
CC_CppHandle<Vec2>* handle = new CC_CppHandle<Vec2>(obj); | |
JsValueRef jsValue; | |
ExceptIfError(JsCreateExternalObject(handle, nullptr/*finalizeCallback*/, &jsValue)); | |
ExceptIfError(JsSetPrototype(jsValue, __js_prototype_Vec2)); | |
heapObj->SetCCHandle(jsValue); | |
return jsValue; | |
}; | |
void JsToCpp(std::shared_ptr<Vec2>& obj, JsValueRef& jsValue) { | |
CC_CppHandle<Vec2>* handle; | |
ExceptIfError(JsGetExternalData(jsValue, (void**)&handle)); | |
obj = handle->GetSmart(); | |
}; | |
void JsToCpp(Vec2& obj, JsValueRef& jsValue) { | |
CC_CppHandle<Vec2>* handle; | |
ExceptIfError(JsGetExternalData(jsValue, (void**)&handle)); | |
obj = *handle->GetPointer(); | |
}; | |
// End shims for Vec2 | |
void CC_InitializeBindings() { | |
// Get the global JS object | |
JsValueRef globalObject; | |
ExceptIfError(JsGetGlobalObject(&globalObject)); | |
{ | |
// Binding class Vec2 | |
// Create new JS prototype | |
ExceptIfError(JsCreateObject(&__js_prototype_Vec2)); | |
JsValueRef bindTarget = __js_prototype_Vec2; | |
{ | |
// Generating binding for constructor Vec2 | |
JsValueRef jsConstructor; | |
ExceptIfError(ch::WrapNativeMethod(&jsConstructor, | |
[](JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argCount, void* callbackState) -> JsValueRef { | |
// Get metadata from function declaration | |
CC_ConstructorMeta* meta = (CC_ConstructorMeta*)callbackState; | |
// Unpack each argument | |
float argument_x; | |
JsToCpp(argument_x, arguments[1]); | |
float argument_y; | |
JsToCpp(argument_y, arguments[2]); | |
// Create C++ object | |
Vec2* external = new Vec2( | |
argument_x, | |
argument_y | |
); | |
// Wrap the C++ object, attach the prototype, and return | |
auto jsReturnValue = CppToJs(external); | |
return jsReturnValue; | |
})); | |
// Get the namespace object to define the ctor on | |
bool has; | |
ExceptIfError(ch::HasPropertyByName(globalObject, "Math", has)); | |
JsValueRef namespaceObject; | |
if (!has) { | |
// If the namespace doesn't exist yet, create it | |
ExceptIfError(JsCreateObject(&namespaceObject)); | |
ExceptIfError(ch::SetPropertyValueByName(globalObject, "Math", namespaceObject)); | |
} else { | |
// The namespace already exists, just get it | |
ExceptIfError(ch::GetPropertyValueByName(globalObject, "Math", &namespaceObject)); | |
} | |
// Push constructor onto namespace object | |
ExceptIfError(ch::SetPropertyValueByName(namespaceObject, "Vec2", jsConstructor)); | |
// End binding for constructor Vec2 | |
} | |
{ | |
// Generating binding for method Length | |
JsValueRef jsFuncValue; | |
ExceptIfError(ch::WrapNativeMethod(&jsFuncValue, | |
[](JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argCount, void* callbackState) -> JsValueRef { | |
Vec2* external; | |
JsToCpp(external, arguments[0]); | |
// Call native function | |
auto returnValue = | |
external->Length( | |
); | |
// Wrap and return native return value | |
return CppToJs(returnValue); | |
})); | |
// Set the property on the prototype | |
ExceptIfError(ch::SetPropertyValueByName(bindTarget, "Length", jsFuncValue)); | |
// End binding for method Length | |
} | |
{ | |
// Generating binding for method Add | |
JsValueRef jsFuncValue; | |
ExceptIfError(ch::WrapNativeMethod(&jsFuncValue, | |
[](JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argCount, void* callbackState) -> JsValueRef { | |
Vec2* external; | |
JsToCpp(external, arguments[0]); | |
// Unpack each argument | |
Vec2 argument_other; | |
JsToCpp(argument_other, arguments[1]); | |
// Call native function | |
auto returnValue = | |
external->Add( | |
argument_other | |
); | |
// Wrap and return native return value | |
return CppToJs(returnValue); | |
})); | |
// Set the property on the prototype | |
ExceptIfError(ch::SetPropertyValueByName(bindTarget, "Add", jsFuncValue)); | |
// End binding for method Add | |
} | |
{ | |
// Generating binding for method Mul | |
JsValueRef jsFuncValue; | |
ExceptIfError(ch::WrapNativeMethod(&jsFuncValue, | |
[](JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argCount, void* callbackState) -> JsValueRef { | |
Vec2* external; | |
JsToCpp(external, arguments[0]); | |
// Unpack each argument | |
Vec2 argument_other; | |
JsToCpp(argument_other, arguments[1]); | |
// Call native function | |
auto returnValue = | |
external->Mul( | |
argument_other | |
); | |
// Wrap and return native return value | |
return CppToJs(returnValue); | |
})); | |
// Set the property on the prototype | |
ExceptIfError(ch::SetPropertyValueByName(bindTarget, "Mul", jsFuncValue)); | |
// End binding for method Mul | |
} | |
{ | |
// Generating binding for method Scale | |
JsValueRef jsFuncValue; | |
ExceptIfError(ch::WrapNativeMethod(&jsFuncValue, | |
[](JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argCount, void* callbackState) -> JsValueRef { | |
Vec2* external; | |
JsToCpp(external, arguments[0]); | |
// Unpack each argument | |
float argument_scale; | |
JsToCpp(argument_scale, arguments[1]); | |
// Call native function | |
auto returnValue = | |
external->Scale( | |
argument_scale | |
); | |
// Wrap and return native return value | |
return CppToJs(returnValue); | |
})); | |
// Set the property on the prototype | |
ExceptIfError(ch::SetPropertyValueByName(bindTarget, "Scale", jsFuncValue)); | |
// End binding for method Scale | |
} | |
{ | |
// Generating binding for method toString | |
JsValueRef jsFuncValue; | |
ExceptIfError(ch::WrapNativeMethod(&jsFuncValue, | |
[](JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argCount, void* callbackState) -> JsValueRef { | |
Vec2* external; | |
JsToCpp(external, arguments[0]); | |
// Call native function | |
auto returnValue = | |
external->toString( | |
); | |
// Wrap and return native return value | |
return CppToJs(returnValue); | |
})); | |
// Set the property on the prototype | |
ExceptIfError(ch::SetPropertyValueByName(bindTarget, "toString", jsFuncValue)); | |
// End binding for method toString | |
} | |
{ | |
// Generating binding for method AsArray | |
JsValueRef jsFuncValue; | |
ExceptIfError(ch::WrapNativeMethod(&jsFuncValue, | |
[](JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argCount, void* callbackState) -> JsValueRef { | |
Vec2* external; | |
JsToCpp(external, arguments[0]); | |
// Call native function | |
auto returnValue = | |
external->AsArray( | |
); | |
// Wrap and return native return value | |
return CppToJs(returnValue); | |
})); | |
// Set the property on the prototype | |
ExceptIfError(ch::SetPropertyValueByName(bindTarget, "AsArray", jsFuncValue)); | |
// End binding for method AsArray | |
} | |
{ | |
// Generating binding for method FromArray | |
JsValueRef jsFuncValue; | |
ExceptIfError(ch::WrapNativeMethod(&jsFuncValue, | |
[](JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argCount, void* callbackState) -> JsValueRef { | |
Vec2* external; | |
JsToCpp(external, arguments[0]); | |
// Unpack each argument | |
std::vector<float> argument_vec; | |
JsToCpp(argument_vec, arguments[1]); | |
// Call native function | |
auto returnValue = | |
external->FromArray( | |
argument_vec | |
); | |
// Wrap and return native return value | |
return CppToJs(returnValue); | |
})); | |
// Set the property on the prototype | |
ExceptIfError(ch::SetPropertyValueByName(bindTarget, "FromArray", jsFuncValue)); | |
// End binding for method FromArray | |
} | |
{ | |
// Generating binding for property x | |
ExceptIfError(ch::DefineProperty(bindTarget, "x", false, | |
[](JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argCount, void* callbackState) -> JsValueRef { | |
Vec2* external; | |
JsToCpp(external, arguments[0]); | |
return CppToJs(external->x); | |
}, | |
[](JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argCount, void* callbackState) -> JsValueRef { | |
Vec2* external; | |
JsToCpp(external, arguments[0]); | |
JsToCpp(external->x, arguments[1]); | |
return ch::Undefined(); | |
}, true)); | |
// End binding for property x | |
} | |
{ | |
// Generating binding for property y | |
ExceptIfError(ch::DefineProperty(bindTarget, "y", false, | |
[](JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argCount, void* callbackState) -> JsValueRef { | |
Vec2* external; | |
JsToCpp(external, arguments[0]); | |
return CppToJs(external->y); | |
}, | |
[](JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argCount, void* callbackState) -> JsValueRef { | |
Vec2* external; | |
JsToCpp(external, arguments[0]); | |
JsToCpp(external->y, arguments[1]); | |
return ch::Undefined(); | |
}, true)); | |
// End binding for property y | |
} | |
// Done binding class Vec2 | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment