问题
I'm working on a project that is going to use JavascriptCore to run javascript in a native app. I'm able to bind a C native object with the JSClassDefinition class and set up the static functions and values that I want to export to Javascript. My problem now is that I want to bind a struct that has attributes of type other structs. The code that works is this :
struct Person {
string name;
string lastName;
int age;
int salary;
int getSalary()
{
return salary;
}
};
.......
JSClassRef PersonClass() {
static JSClassRef person_class;
if (!person_class) {
JSClassDefinition classDefinition = kJSClassDefinitionEmpty;
static JSStaticFunction staticFunctions[] = {
{ "setSalary", set_salary, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ 0, 0, 0 }
};
static JSStaticValue staticValues[] = {
{ "name", person_get_name, 0, kJSPropertyAttributeDontDelete },
{ "lasName", person_get_lastName, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ 0, 0, 0, 0 }
};
classDefinition.className = "Person";
classDefinition.attributes = kJSClassAttributeNone;
classDefinition.staticFunctions = staticFunctions;
classDefinition.staticValues = staticValues;
classDefinition.finalize = person_finalize;
classDefinition.callAsConstructor = person_CallAsConstructor;
person_class = JSClassCreate(&classDefinition);
}
return person_class;
}
.......
JSEvaluateScript(globalContext, JSStringCreateWithUTF8CString("function changeSalary(person) { person.setSalary(200); return true;}"), nullptr, nullptr, 1, nullptr)
........
Person *e = new Person();
e->salary = 100;
e->age = 34;
JSValueRef changeSalaryFunc = JSObjectGetProperty(globalContext, globalObject, JSStringCreateWithUTF8CString("changeSalary"),nullptr);
JSObjectRef object = JSValueToObject(globalContext, changeSalaryFunc, nullptr);
JSValueRef exception = 0;
int argumentCount = 1;
JSValueRef arguments[argumentCount];
JSObjectRef ref = JSObjectMake(globalContext, PersonClass(), static_cast<void*>(e));
arguments[0] = ref;
JSValueRef result = JSObjectCallAsFunction(globalContext, object, 0, argumentCount, arguments, &exception);
But I'm facing the problem that the code should handle this structure.
struct Address {
string street;
int number;
};
struct Person {
string name;
string lastName;
int age;
int salary;
Address address;
int getSalary()
{
return salary;
}
};
How can I bind this kind of structure? because I want to use a code like this.
JSEvaluateScript(globalContext, JSStringCreateWithUTF8CString("function address_number(person) { return person.address.number;}"), nullptr, nullptr, 1, nullptr);
Thanks for reading.
回答1:
I achieved to get the binding with these structures. I made the follow steps to do it.
1.- You should bind the Address structure as I did with Person.
2.- You have to create the bind method for the constructor for the Person structure and inside it initiate the Address object and set it as property like this:
// Constructor
JSObjectRef PersonCallAsConstructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
Person *privObj = new Person();
if (argumentCount >= 2) {
if (JSValueIsString(ctx, arguments[0]))
privObj->name = JSStringToStdString(JSValueToStringCopy(ctx, arguments[0], nullptr));
if (JSValueIsString(ctx, arguments[1]))
privObj->lastName = JSStringToStdString(JSValueToStringCopy(ctx, arguments[1], nullptr));
}
// the third argument passed to the person constructor is the address street
if (argumentCount >= 3) {
if (JSValueIsString(ctx, arguments[2]))
privObj->address.street = JSStringToStdString(JSValueToStringCopy(ctx, arguments[2], nullptr));
}
// initiate a new Address object
JSObjectRef addressObj = AddressJSObjectMake(ctx, &privObj->address);
JSObjectSetProperty(ctx, constructor, JSStringCreateWithUTF8CString("address"), addressObj, kJSPropertyAttributeNone, nullptr);
JSObjectSetPrivate(constructor, static_cast<void*>(privObj));
return constructor;
}
来源:https://stackoverflow.com/questions/47103252/binding-native-objects-with-javascriptcore-c-api