运行时故障类包装C对象
runtime failure class wrapping C object
我正在更新节点mapserver,它将类重构分支中的mapserver库封装为更可维护的代码结构(基于节点ogr的组织结构进行更改)。
到目前为止,我已经重构了主模块接口,并开始处理第一个要包装的类,一个名为errorObj
的mapserver 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构建27.2中看到。我在堆栈跟踪中找不到任何特别有用的东西。
扩展构建和一些测试通过(从库本身导出的符号和方法),但当库试图创建一个包装C对象的Object时失败。
在javascript中,我调用mapserver.getError()
。在扩展中,这将调用映射服务器方法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
为null,这意味着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();
}
答案是上面的代码很好。实际错误是MSError::构造函数未初始化,因为我忽略了从主模块代码中调用它。实际的null对象是MSError::constructor->GetFunction()。
感谢Ben Noordhuis为我们指明了正确的方向。
- 包装一个对象并假装它是一个 int
- 错误:"释放后使用包装器对象 (WRAPPER_ESCAPE)"
- C++包装库:在堆栈上分配C++ C 中的对象
- 将对象传递给函数而不将其包装到 std::ref 中,而参数被指定为 const 引用
- 在 C++ 对象包装器中安全地包含 C 代码
- 如何将 c++ 类包装到 python 中,以便我可以使用 pybind11 访问其成员的公共方法(成员是一个对象指针)
- 在 C++ 中为 C 样式对象创建一个透明包装类
- 如何将包装类的对象用作包装函数中的参数
- 如何包装对象,使它们成为无法交互的单独类型?
- 由 pybind11 包装的对象的内存开销
- 将抽象值对象保存在包装器中和继承的用法中
- 将numpy对象传递到Pythonqt包装器
- 如何将 Python 中的字节对象传递给用 Swig 包装的C++函数
- 将 C 对象的数组包装到类C++
- 泛型对象包装器
- OpenGL对象包装器中的自动绑定
- 如何编写安全的原子对象包装器?
- 我的GLSL着色器对象/包装器是否应该封装加载/设置VertexArrayObject
- 将C++对象包装在外部“C”中
- 移动值/对象包装器的构造函数