2015-10-09 4 views
0

Мне нужно немного больше информации о том, как реализовать создаваемые emscripten классы в javascript. У меня есть следующий интерфейс в C++, но его нужно реализовать на стороне javascript.Реализация интерфейса Javascript Emscripten

class OsHttp { 
public: 
    virtual ~OsHttp() {} 

    virtual void request(const std::string & verb, const std::string & url, const std::string & body, const std::unordered_map<std::string, std::string> & headers, const std::shared_ptr<HttpCallback> & callback) = 0; 
}; 

Я знаю, что следующий будет, чтобы я начал, но как я реализовать конструктор и т.д.

var osHttp = { 
    constructor: function(){} 
    request: function(verb, url, body, headers, callback) { 
     console.log('OsHttp with: ' + verb); 
    } 
}; 

var OsHttpObject = Module.OsHttp.implement(osHttp); 

ответ

2

Если я понять, что вы после этого, то вам нужно иметь некоторые способ общения между мирами Javascript и C++. Кроме того, я думаю, что если вы хотите использовать объект, реализующий этот интерфейс на C++, то для его компиляции и запуска должна быть конкретная реализация интерфейса на C++. Тогда эта реализация интерфейса вызовет Javascript.

Чтобы сделать это, вы могли бы использовать EM_ASM_* macros в классе, который реализует интерфейс:

class OsHttpImplementation : public OsHttp { 
public: 
    ~OsHttp() 
    { 
     EM_ASM({ 
     // Cleanup anything in Javascript context 
     }); 
    } 

    void request(const std::string & verb, const std::string & url, const std::string & body, const std::unordered_map<std::string, std::string> & headers, const std::shared_ptr<HttpCallback> & callback) 
    { 
     // Probably a good idea to save any shared pointers as members in C++ 
     // so the objects they point to survive as long as you need them 

     int returnValue = EM_ASM_INT_V({ 
      // Example ways of accessing data from C++ 
      var verb = Pointer_stringify($0); 
      var url = Pointer_stringify($1); 
      var body = Pointer_stringify($2); 
      var callbackFunctionPointer = $3; 

      // Something here that makes an HTTP request, creates any objects, etc. 

      return 0; 

     }, verb.c_str(), url.c_str(), body.c_str(), callback.get()); 
    } 
}; 

Если вы хотите есть на самом деле является объектом в JavaScript, который соответствует объекту в C++, вы, возможно, придется немного ручного управления в Javascript для создания/хранения/удаления объектов на каком-то заводе. В частности, им нужно будет хранить их где-нибудь, чтобы C++ мог получить доступ к правильному через какой-то ключ. Указатель на «это» может быть удобно для этого:

class OsHttpImplementation : public OsHttp { 
public: 
    OsHttp() 
    { 
     EM_ASM_V({ 
     var thisPointer = $0; 
     OsHttpFactory.construct(thisPointer); 
     }, this); 
    } 

    ~OsHttp() 
    { 
     EM_ASM({ 
     var thisPointer = $0; 
     OsHttpFactory.destruct(thisPointer); 
     }, this); 
    } 

    void request(const std::string & verb, const std::string & url, const std::string & body, const std::unordered_map<std::string, std::string> & headers, const std::shared_ptr<HttpCallback> & callback) 
    { 
     int returnValue = EM_ASM_INT_V({ 
      var thisPointer = $0; 
      OsHttpFactory.get(thisPointer).request($1, $2, $3, $4); 
     }, this, verb.c_str(), url.c_str(), body.c_str(), callback.get()); 
    } 
}; 

У вас есть много свободы на реализацию OsHttpFactory в JavaScript. Вы не упомянули, если вы хотите, чтобы это в браузере, но если вы делаете, и используете XMLHttpRequests, вы могли бы иметь что-то вроде

(function(context) { 

    var store = {} 

    function OsHttp() { 
    this.request = null; 
    } 

    OsHttp.prototype.request = function(verb, url, body, callbackPointer) { 
    var request = this.request = new XMLHttpRequest(); 
    request.onreadystatechange = function() { 
     if (request.readyState == 4) { 
     // Might need other arguments if you want to pass something back to C++ 
     Module.Runtime.dynCall('v', callbackPointer, []); 
     } 
    }); 
    this.request.open(verb, url, true); 
    this.request.send(); 
    }; 

    OsHttp.prototype.cleanup = function() { 
    // Do something to cleanup in-progress requests etc. 
    } 

    context.OsHttpFactory = { 
    construct: function(thisPointer) { 
     store[thisPointer] = new OsHttp(); 
    }, 
    destruct: function(thisPointer) { 
     store[thisPointer].cleanup(); 
     delete store[thisPointer]; 
    }, 
    get: function(thisPointer) { 
     return store[thisPointer]; 
    } 
    }; 

})(window); 

Тогда в C++ вы можете использовать его в качестве стандартного класса:

// Run constructors 
auto osHttp = new OsHttpImplementation(); 

// Make request 
osHttp->request(....); 

// Run destructors, and remove object from the Javascript store 
delete osHttp; 

Должен сказать, все это немного издевательствует!

+0

Спасибо @MichalCharemza, это отличный совет! –

Смежные вопросы