How to pass C++ object to JavaScript function using JavaScriptCore

╄→尐↘猪︶ㄣ 提交于 2020-01-03 04:40:27

问题


I've written a function in JavaScript in an external JavaScript file sample.js .

function fileInfo(obj)
{
    /////
}

I have a class defined in the sample.cpp file as follows :

class sample
{
   int i;
   ///
};

///

int main()
{
   sample obj;
   ///
   ///
}

How can we pass obj to the JavaScript function "fileInfo" as a parameter?


回答1:


You cannot directly pass an object encoded in one programming language to another program written in a different programming language. This is not possible since the binary layout of objects differ from one programming language to another. For instance, in JavaScript the Number type is a 64-bit float (8 bytes). If your C++ object uses an int32 (4 bytes), then the layout of both objects in memory differ. Both objects should have the same size (8 bytes), at least, to be compatible (actually it gets much more complicated than that). In summary, in order to exchange values between different programming languages you need either to agree in a neutral format or to convert between data types.

The FFI (Foreign Function Interface) JavaScript libraries for C/CCP/Objective-C, etc allows you to keep ABI compatibility between C and JavaScript programs. If you need to mingle C/CPP and JavaScript code you can use the javascriptcoregtk library.

Going back to your example, you will need to convert your Sample CPP object to a JSCValue object to make it work. A casting is not enough, for the reasons I commented in the first paragraph (the programmer needs to decide how the conversion between the CPP object and its equivalent in JavaScript should look like). Here is a possible solution:

/**
 * Pass CPP object to JavaScript function
 * 
 * sample.js:
 * function fileInfo(obj)
 * {
 *  return "fileInfo: " + obj.i;
 * }
 * 
 * To compile: g++ main.cc -o main `pkg-config --cflags --libs javascriptcoregtk-4.0`
 *
 */

#include <iostream>
#include <string>
#include <fstream>
#include <streambuf>

#include <jsc/jsc.h>

using namespace std;

class Sample {
public:
    Sample(int i) { this->i = i; };
    JSCValue* toJSObject(JSCContext* jsContext);
    int i;
};

JSCValue* Sample::toJSObject(JSCContext* jsContext)
{
    JSCValue* ret = jsc_value_new_object(jsContext, nullptr, nullptr); 

    JSCValue* i = jsc_value_new_number(jsContext, this->i);
    jsc_value_object_define_property_data(ret, "i", JSC_VALUE_PROPERTY_ENUMERABLE, i);

    return ret;
}

int main(int argc, char* argv[])
{
    // Create jsContext.
    JSCContext* jsContext = jsc_context_new();

    // Load JavaScript file.
    const std::string filename = {"sample.js"};
    ifstream t("sample.js");
    string code((std::istreambuf_iterator<char>(t)),
            std::istreambuf_iterator<char>());
    JSCValue* ret = jsc_context_evaluate(jsContext, code.c_str(), static_cast<gssize>(code.length()));

    // Query 'fileInfo' and store it into JSCValue.
    JSCValue* fileInfo = jsc_context_evaluate(jsContext, "fileInfo", 8);
    if (!jsc_value_is_function(fileInfo)) {
        cerr << "Couldn't find function 'fileInfo'" << endl;
        exit(EXIT_FAILURE);
    }

    // Create CPP object.
    Sample obj(42);

    // Convert to JSCValue object and call 'fileInfo' function.
    ret = jsc_value_function_call(fileInfo, JSC_TYPE_VALUE, obj.toJSObject(jsContext), G_TYPE_NONE);
    cout << "ret: [" << jsc_value_to_string(ret) << "]" << endl;

    return 0;
}

NOTE: I didn't free memory in the example above to avoid adding complexity.

The method Sample::toJSObject casts your CPP object to a JSCValue object. Then the function call jsc_value_function_call(fileInfo, JSC_TYPE_VALUE, obj.toJSObject(jsContext), G_TYPE_NONE); executes function fileInfo (previously loaded in this JavaScript context) and passes a "cast" version of the CPP object. The result after executing this program is:

ret: [fileInfo: 42]


来源:https://stackoverflow.com/questions/57003419/how-to-pass-c-object-to-javascript-function-using-javascriptcore

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!