在JS中,我调用C++函数,如下所示:
var req = new IO.HttpRequest(IO.RequestType.get);
req.data({ i: 'jTKvNf9w' }).send('http://pastebin.com/raw.php', function (content) { console.log(content); });请求将被异步处理,一旦完成,回调就会被调用。在C++中,发送函数如下所示:
void XmlHttpRequest::open(const Utils::String& str, ::JS::FunctionObjPtr callback) {
mCallback = callback;
mRequest->open(str);
}如果请求完成后:
void XmlHttpRequest::onComplete(Utils::String content) {
sUIMgr->getDispatcher()->pushFrame(Gl::Dispatcher::Priority::Low, [this, content]() {
::JS::FunctionObjPtr f = mCallback;
f->callVoid(content);
});
}推送框架将函数放入要在设置所有脚本的主线程中执行的队列中。
现在问题是在callVoid中,当HeapObject::GetHeap()调用MemoryChunk::FromAddress(reinterpret_cast<Address>(this))->heap();时,我会遇到访问冲突。这些是v8函数。问题是,this-Pointer在HeapObject中是0xCCCCCC,这意味着它是一个未初始化的值。this-Pointer来自存储在JS::FunctionObjPtr中的句柄(std::shared_ptr的typedef )。
一开始我认为我的FunctionObj有问题。我是通过以下方式获得这一信息的:
template<typename T>
static TYPE_RET(FunctionObjPtr) ObjectWrap::unwrap(v8::Handle<v8::Value>& value) {
if (value->IsFunction() == false) {
TYPE_ERR("Value is not a function");
}
return std::make_shared<FunctionObj>(value);
}TYPE_RET只是在做一些模板元编程工作。FunctionObj看起来如下所示:
class FunctionObj
{
v8::Handle<v8::Value> mHandle;
public:
FunctionObj(v8::Handle<v8::Value>& fun) {
mHandle = fun;
}
FunctionObj() { }
operator bool () {
return mHandle.IsEmpty() == false;
}
template<typename... Args>
void callVoid(const Args&... args) {
std::vector<v8::Handle<v8::Value>> arguments;
addArgument(arguments, args...);
v8::TryCatch tc;
v8::Handle<v8::Function>::Cast(mHandle)->Call(mHandle, arguments.size(), arguments.data());
if (tc.HasCaught()) {
throw JS::Exception(tc.Exception(), tc.StackTrace());
}
}
};当我在XmlHttpRequest::open中调用它的“注册”函数时,它可以工作。因此,起初我认为对象会被gc‘编辑,但是为了确保它永远不会在FunctionObj::FunctionObj中收集,我从句柄中创建了一个v8::Persistent。但还是坠毁了。我甚至制作了v8::Persistent,以查看它是否真的被收集到,但是弱回调从未被调用过。
我在打电话之前查过的其他事情:
更多信息:这不仅限于v8::Handle。如果我试图存储一个对象并在以后访问它的一个属性,也会发生这种情况。我只是不能在那个用手柄的羔羊里面找到任何东西。
发布于 2014-04-04 11:20:46
正如我在我尝试过的事情中所说的,我看了一下v8::Persistent。结果发现我用错了。
我所做的:
class FunctionObj
{
v8::Handle<v8::Value> mHandle;
v8::Persistent<v8::Value> mPersistent;
public:
FunctionObj(v8::Handle<v8::Value>& fun) {
mPersistent.Reset(v8::Isolate::GetCurrent(), fun);
mHandle = fun;
}
FunctionObj() { }
operator bool () {
return mHandle.IsEmpty() == false;
}
template<typename... Args>
void callVoid(const Args&... args) {
std::vector<v8::Handle<v8::Value>> arguments;
addArgument(arguments, args...);
v8::TryCatch tc;
v8::Handle<v8::Function>::Cast(mHandle)->Call(mHandle, arguments.size(), arguments.data());
if (tc.HasCaught()) {
throw JS::Exception(tc.Exception(), tc.StackTrace());
}
}
};我应该做的
class FunctionObj
{
v8::Persistent<v8::Value> mPersistent;
public:
FunctionObj(v8::Handle<v8::Value>& fun) {
mPersistent.Reset(v8::Isolate::GetCurrent(), fun);
}
FunctionObj() { if(mPersistent) { mPersistent.Dispose(); } }
operator bool () {
return mHandle.IsEmpty() == false;
}
template<typename... Args>
void callVoid(const Args&... args) {
std::vector<v8::Handle<v8::Value>> arguments;
addArgument(arguments, args...);
v8::Local<v8::Function> fun = v8::Local<v8::Function>::New(v8::Isolate::GetCurrent(), mPersistent.As<v8::Function>());
v8::TryCatch tc;
fun->Call(fun, arguments.size(), arguments.data());
if (tc.HasCaught()) {
throw JS::Exception(tc.Exception(), tc.StackTrace());
}
}
};我创建的持久化并不意味着我存储的句柄不会被销毁,只意味着以后可以查询对象的新句柄,并且对象不会被删除。
现在所有的一切都像一种魅力!
https://stackoverflow.com/questions/22856836
复制相似问题