2013-07-05 15 views
3

我正在更新node-mapserver,将class-refactor分支中的mapserver库更新为更易维护的代码结构(基于对组织node-ogr的更改)。运行时间失败类包装C对象

到目前为止,我已经重构了主模块接口,并开始对第一个类进行封装,一个名为errorObj的地图服务器C结构,我用class MSError包装。扩展构建,但我面临的是扩展中的一个运行时断言错误,我第一次触发一个新的MSError对象来包装一个errorObj。

Fatal error in ../deps/v8/src/api.h, line 297 
CHECK(allow_empty_handle || that != __null) failed 

节点0.10有一个非常冗长的堆栈跟踪,可以在travis build 27.2中看到。我在堆栈跟踪中找不到任何特别有用的东西。

扩展构建和一些测试传递(从库本身导出的符号和方法),但在库试图创建一个包装C对象的对象时失败。我的电话是mapserver.getError()。在扩展中,这会调用mapserver方法errorObj* err = msGetErrorObj();并返回return scope.Close(MSError::New(err));。 MSError的New方法做到这一点:

Handle<Value> MSError::New(errorObj *err) { 
    HandleScope scope; 
    MSError *wrapped = new MSError(err); 
    Handle<Value> ext = External::New(wrapped); 
    Handle<Object> obj = MSError::constructor->GetFunction()->NewInstance(1, &ext); 
    return scope.Close(obj); 
} 

我试图调试该用gdb,我可以摆脱它与我的技能有限,最好是错误在这个调用发生:

Handle<Object> obj = MSError::constructor->GetFunction()->NewInstance(1, &ext); 

我可以从中得到的是ext为空,这意味着External::New(wrapped)调用没有返回有效值。我已确认errorObj* err确实指向了一个有效的,正确初始化的errorObj结构。为了澄清,没有实际的错误,mapserver总是返回一个有效的errorObj,但是如果此时没有错误,则代码为0。

这里是希望的相关代码。

ms_error.hpp

#ifndef __NODE_MS_ERROR_H__ 
#define __NODE_MS_ERROR_H__ 

#include <v8.h> 

#include <node.h> 
#include <node_object_wrap.h> 

#include <mapserver.h> 

using namespace v8; 
using namespace node; 

class MSError: public node::ObjectWrap { 
    public: 
    static Persistent<FunctionTemplate> constructor; 
    static void Initialize(Handle<Object> target); 
    static Handle<Value> New(const Arguments &args); 
    static Handle<Value> New(errorObj *err); 

    MSError(); 
    MSError(errorObj *err); 
    inline errorObj *get() { return this_; } 

    private: 
    ~MSError(); 
    errorObj *this_; 
}; 

#endif 

ms_error.cpp

#include "ms_error.hpp" 

Persistent<FunctionTemplate> MSError::constructor; 

void MSError::Initialize(Handle<Object> target) { 
    HandleScope scope; 

    constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(MSError::New)); 
    constructor->InstanceTemplate()->SetInternalFieldCount(1); 
    constructor->SetClassName(String::NewSymbol("MSError")); 

    // constructor->InstanceTemplate()->SetNamedPropertyHandler(MSError::NamedPropertyGetter, NULL, MSError::NamedPropertyQuery, NULL, MSError::NamedPropertyEnumerator); 

    target->Set(String::NewSymbol("MSError"), constructor->GetFunction()); 
} 

MSError::MSError(errorObj *err) : ObjectWrap(), this_(err) { } 

MSError::MSError() : ObjectWrap(), this_(0) { } 

MSError::~MSError() { } 

Handle<Value> MSError::New(const Arguments& args) 
{ 
    HandleScope scope; 

    if (!args.IsConstructCall()) 
    return ThrowException(String::New("Cannot call constructor as function, you need to use 'new' keyword")); 

    if (args[0]->IsExternal()) { 
    Local<External> ext = Local<External>::Cast(args[0]); 
    void *ptr = ext->Value(); 
    MSError *f = static_cast<MSError *>(ptr); 
    f->Wrap(args.This()); 
    return args.This(); 
    } 

    return args.This(); 
} 

回答

2

这个问题的答案是,上面的代码是好的。实际的错误是MSError ::构造函数未初始化,因为我忽略了从主模块代码调用它。实际的空对象是MSError :: constructor-> GetFunction()。

感谢Ben Noordhuis为我们指出了正确的方向。

相关问题