4

C ++からのネストされた関数呼び出しでローカル変数を検索する方法を誰かが知っていますか?次の例を考えてみましょう。

// e.g. a global variable in the browser
var global = "global_value";

function foo(){
    var global = "local_value";
    myCppFunction("global", global);
}

foo();

私の質問は、実装においてmyCppFunction、関数ローカル変数「グローバル」(値ではなく、これは2番目のパラメーターによって与えられます)に「foo」からどのようにアクセスできるかということです。

Handle<Value> MyCppFunction(const Arguments& args){
    Local<String> varName = args[0]->ToString();
    Local<String> varValue = args[1]->ToString(); // this holds "local_value"
    // how to access the variable "global" in the scope of 'foo' ?
}
4

1 に答える 1

4

なんとか自分で見つけました。スタック上の値を見つける方法については、以下の例を参照してください(また、ここでは文字列変数の例に置き換えます)。

事前の2つの発言:

  • マスター論文でこれを使用する非常にユースケースを除いて、これを望ましくない動作についてテストしていません-ドラゴンが存在する可能性があります。
  • テストで目的のスタックフレームが生成される理由は正確にはわかりませんがsfl.FindJavaScriptFrame(0)、呼び出し深度とは関係なく機能するため、0でインデックス付けされたスタックフレームは常に直接の呼び出し元のフレームであると思われます(私の場合、私はまさにそれが欲しい)。

そしてコード:

// Prepare identification of the variable,assuming varName as in the question
// More convenient conversions would be appreciated, at least by me
Local<String> varName = args[0]->ToString();        
std::string varStr = *String::AsciiValue(varName);
// I'm using 'namespace i = internal;' (within v8-namespace)
i::Vector<const char> tmpVar(varStr.data(), varStr.length());
i::Handle<i::String> varIStr = i::Isolate::Current()->factory()->NewStringFromAscii(tmpVar, i::TENURED);

// Now hunt down the stack frame of interest, be sure to consider my remarks above
i::StackFrameLocator sfl;
// Comment from the code: The caller must guarantee that such a frame exists.
i::JavaScriptFrame* jsf = sfl.FindJavaScriptFrame(0);
// create some replacement
i::Vector<const char> tmp("there you go", 12);
i::Handle<i::String> insert = i::Isolate::Current()->factory()->NewStringFromAscii(tmp, i::TENURED);
i::Object* insertObj = insert->ToObjectChecked();

// by the help of JavaScriptFrame::Print I came up with this:
i::Object* fun = jsf->function();
if (fun->IsJSFunction()){
    i::Handle<i::ScopeInfo> scope_info(i::ScopeInfo::Empty());
    i::Handle<i::SharedFunctionInfo> shared((i::JSFunction::cast(fun))->shared());
    scope_info = i::Handle<i::ScopeInfo>(shared->scope_info());
    i::Object* script_obj = shared->script();
    if (script_obj->IsScript()) {
        int stack_locals_count = scope_info->StackLocalCount();
        for (int i = 0; i < stack_locals_count; i++) {
            if (scope_info->StackLocalName(i)->Equals(*varIStr)){
                // replace the value on the stack
                jsf->SetExpression(i,insertObj);
            }
        }
    }
}
于 2012-10-23T10:54:44.510 に答える