3

class- refactor ブランチのmapserverライブラリをラップするnode-mapserverを、より保守しやすいコード構造に更新する作業を行っています ( node-ogrの編成に基づいて変更を行います)。

ここまでで、メイン モジュール インターフェイスをリファクタリングし、ラップする最初のクラスから始めましerrorObjclass 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 オブジェクトをラップするオブジェクトを作成しようとすると失敗します。

JavaScript では、 を呼び出します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ことを意味する nullです。有効で適切に初期化された errorObj 構造を指してExternal::New(wrapped)いることを確認しました。errorObj* err明確にするために、実際のエラーはありません。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();
}
4

1 に答える 1

2

これに対する答えは、上記のコードで問題ないということです。実際のエラーは、メイン モジュール コードからの呼び出しを怠ったため、MSError::constructor が初期化されなかったことです。実際の null オブジェクトは MSError::constructor->GetFunction() でした。

Ben Noordhuis に、正しい方向を示してくれてありがとう。

于 2013-07-05T16:56:19.437 に答える