2016-04-11 31 views
1

私はemscriptenを使ってC++プロジェクトをWebに移植しています.C++コードと対話するWebアプリケーションはNodeJsにあります。javascriptライブラリを使用してemscriptenでSocket.ioを使用するにはどうすればよいですか?

私はNode.jsでSocket.ioを使用しています。私はC++コードでも使用したいので、socket.ioコードを使用するjavascriptライブラリを使用しました。作業。

私はこのケースを実証し、この小さな例書いた:

#include <iostream> 
#include <stdlib.h> 
#include <stdio.h> 
#include <emscripten.h> 

int val = 0; 

extern "C" 
{ 
    extern void send_board(char* flat_board); 
    extern bool receive_board(char** _string_dest); 
} 

void one_iter() 
{ 
    #ifdef SEND 
    char* c = "test"; 

    std::cout << val << std::endl; 

    if(val%1000 == 0){ 
     send_board(c); 
    } 
    val++; 
    #else 
    char* c; 
    if(receive_board(&c)) std::cout << "Received:" << c << std::endl; 
    #endif 
} 


int main() 
{ 
    emscripten_set_main_loop(one_iter, 0, 1); 
    return 0; 
} 

mergeInto(LibraryManager.library, { 
     send_board: function(message) { 
     socket.on('connect', function(){ 
      socket.emit('game_request_sender_pipeline', { 
       message: "Hi", 
      }); 
     }); 
     }, 

     receive_board: function(_string_dest_in_c){ 

     socket.on('connect', function(){ 
      socket.on('game_request_receiver_pipeline' , function (message) 
      { 
       var msg = "Other side : " + message.message; 
       var buffer = Module._malloc(message.message.length + 1); 
       Module.writeStringToMemory(msg, buffer); 
       setValue(_string_dest_in_c, buffer, '*'); 
       return true; 
      }); 
     }); 

     return false; 
     }, 
    }); 

を、私は次のようにコンパイル:

// for the sending test 
em++ main.cpp --js-library path_to_js_library.js -o socket.html -DSEND=1 
// for the receiving test 
em++ main.cpp --js-library path_to_js_library.js -o socket.html 

とのNode.jsサーバーコードで、私は持っています:

io.on('connection', function (socket) { 

     socket.on('game_request_sender_pipeline' , function (message) 
     {  
      console.log("game_request_sender_pipeline on."); 
      socket.broadcast.emit('game_request_receiver_pipeline', { 
       message: message.message, 
      }); 
      console.log("game_request_receiver_pipeline emitted."); 
     }); 
}); 

私はそれがうまくいかないと思ったので、nodejsサーバーをキャンセルして再起動して、ブラウザのコンソールに結果が表示されました。

+0

'(one_iterに触発さ


)'同期しているが、 'receive_board'は、非同期のようです。 – zakki

+0

非同期の性質を持つ回避策にコールバックを実装する必要がありますか? –

+0

私はそう思います。'emscripten_set_main_loop'の3番目のパラメータがtrueの場合、one_iterは何度も呼び出されます。 – zakki

答えて

2

コメントの示唆には意味があるようです。

emscripten_set_main_loopは、しかし、JavaScript APIのからの呼び出しが原因socket.io

に非同期であるので、問題を解決する代わりにreturnステートメントを使用すると、条件付きで、私はそれかどうかwant-コードを実行し、同期動作をシミュレートするでしょう真実か偽であるか - 私はコールバックを使うことを考えました。

アイデアは、このように書き:メインループでは

  1. を、そこreceive_boardへの呼び出しになるだろう。
  2. receive_boardは、成功コールバックと失敗コールバックをパラメータとして受け取る予定です。 (コールバックはC関数です)
  3. コールバックはModule.ccallを使用してコールします。
  4. コールバックは、実際にそのキーワードを書いて避けるために、私は、我々は、関数定義でキーワードEMSCRIPTEN_KEEPALIVEを使用する必要がありますccallを使用するためには、順番に領収書

時に条件付きで実行したいコードが含まれています定義されるコールバックごとに、コールバックを呼び出す関数の1つのみに使用することにしました。

extern "C" 
{ 
EMSCRIPTEN_KEEPALIVE void callback_invoker(void* fn_ptr, void* fn_arg) 
{ 
    // some kind of cast to the original function signature, and to the original fn_arg type 
    (*fn_ptr)(fn_arg); 
} 
} 

とJavaScript側で

mergeInto(LibraryManager.library, { 
     receive_board: function(_string_dest_in_c, succcess_callback, failure_callback, s_cb_arg, f_cb_arg){ 

     socket.on('connect', function(){ 
      socket.on('game_request_receiver_pipeline' , function (message) 
      { 
       var msg = "Other side : " + message.message; 
       var buffer = Module._malloc(message.message.length + 1); 
       Module.writeStringToMemory(msg, buffer); 
       setValue(_string_dest_in_c, buffer, '*'); 
       Module.ccal('callback_invoker', 'void', ['number', 'number'], [success_callback, s_cb_arg]); 
       return; 
      }); 
     }); 

     Module.ccal('callback_invoker', 'void', ['number', 'number'], [failure_callback, f_cb_arg]); 
     }, 
    }); 

この方法で、私は上記の問題を解決しました。このanswer

+0

非常にスマートな解決策です。 JS側から動的にメモリを割り当てることについて考えなかった! – Ameo