NPAPIをざっくりやってみる (2)

2013-01-26T00:00:00+00:00 C++ NPAPI

NPAPIで定義したNPObjectなクラス等を実行したメソッド等から値を返したい場合、NPVariant* resultなのに処理すれば良いだと思うので、ちょいと色々やってみた

#include <iostream>
#include "plugin.h"

using namespace std;

void loga(const char* action) {
  cerr << "[" << action << "]" << endl;
}

// std::stringからNPUTF8を生成
NPUTF8* CREATE_NPUTF8(const string s) {
  size_t len = s.size();

  NPUTF8* v = static_cast<NPUTF8*>(ppFuncs->memalloc(len + 1));
  memcpy(v, s.c_str(), len);

  return v;
}

// NPAPIライフサイクル上とかで注入しておく
NPP rootInstance;

// 返す値のNPObject (NPVariantType_Object)
class SampleNPObject : public NPObject {
  public:
    static NPClass npClass;

    static NPObject* Create() {
      return ppFuncs->createobject(rootInstance, &npClass);
    }

    // messageプロパティアクセスであればtrueを返す。falseを返すとプロパティ参照できずにGetProperty等の参照まで及ばない模様
    static bool HasProperty(NPObject* pObj, NPIdentifier name) {
      loga("HasProperty");

      NPUTF8* propertyName = ppFuncs->utf8fromidentifier(name);
      bool hasPropertyExists = strcmp(propertyName, "message") == 0;

      ppFuncs->memfree(propertyName);

      return hasPropertyExists;
    }

    // messageプロパティにアクセスされた際にNPUTF8なNPStringを返り値としてNPVariantに設定
    static bool GetProperty(NPObject* pObj, NPIdentifier name, NPVariant* result) {
      loga("GetProperty");

      NPUTF8* propertyName = ppFuncs->utf8fromidentifier(name);
      bool hasPropertyExists = strcmp(propertyName, "message") == 0;

      if (hasPropertyExists) {
        NPUTF8* s = CREATE_NPUTF8("hoge fuga foobar");

        // 生成したNPUTF8を返り値としてNPVariantに設定
        STRINGZ_TO_NPVARIANT(s, *result);
      }

      ppFuncs->memfree(propertyName);

      return true;
    }
};

class HogeNPObject : public NPObject {
  public:
    static NPClass npClass;

    static bool HasMethod(NPObject *pObj, NPIdentifier name) {
      loga("HasMethod");

      NPUTF8 *methodName = ppFuncs->utf8fromidentifier(name);
      bool result = strcmp(methodName, "eject") == 0;

      ppFuncs->memfree(methodName);

      return result;
    }

    static bool Invoke(NPObject* pObj, NPIdentifier name, const NPVariant *args, uint32_t argc, NPVariant* result) {
      loga("Invoke");

      NPUTF8 *methodName = ppFuncs->utf8fromidentifier(name);
      bool isMatchMethodName = strcmp(methodName, "eject") == 0;

      if (isMatchMethodName)
        /* bool型なデータを返す場合
        BOOLEAN_TO_NPVARIANT(true, *result);
        */

        /* int32なデータを返す場合
        INT32_TO_NPVARIANT(1, *result);
        */

        // SampleNPObjectを返り値として返すようにNPVarinatに設定
        OBJECT_TO_NPVARIANT(SampleNPObject::Create(), *result);
      }

      ppFuncs->memfree(methodName);

      return isMatchMethodName;
    }
};

NPClass HogeNPObject::npClass = {
  NP_CLASS_STRUCT_VERSION,
  NULL, // Alloc
  NULL, // Dealloc
  NULL, // Invalidate
  HogeNPObject::HasMethod,  // hasMethod
  HogeNPObject::Invoke, // Invoke
  NULL, // InvokeDefault
  NULL, // hasProperty
  NULL, // getProperty
  NULL, // setProperty
  NULL, // RemoveProerty
  NULL, // enumerate
  NULL // construct
};

NPClass SampleNPObject::npClass = {
  NP_CLASS_STRUCT_VERSION,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  SampleNPObject::HasProperty,
  SampleNPObject::GetProperty,
  NULL,
  NULL,
  NULL,
  NULL
};

んな感じで、NPVariantに適切なデータを設定する事でJS側から実行された際に返り値として返還させる事が出来る模様

で返り値としてObject型で返したい場合に、なんらかのEmptyなオブジェクトとかを返したり出来るとかそういうのがあるのか不明だったので、返すObjectな定義のNPObjectなクラスを作り(SampleNPObject)、それのインスタンス作って返すような感じ

fluent-plugin-mongoに突っ込んでみる