首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >包装在水稻/ruby中的纯虚拟c++类在运行时引发TypeError (“不是类(Module)")

包装在水稻/ruby中的纯虚拟c++类在运行时引发TypeError (“不是类(Module)")
EN

Stack Overflow用户
提问于 2017-09-08 06:35:23
回答 2查看 105关注 0票数 1

我正在使用水稻-红宝石包装包装一个名为C++库的埃西坦作为红宝石扩展。

在这个库中,有两个名为essentia::standard::Algorithmessentia::streaming::Algorithm的纯虚拟类。我遵循了这些指令并创建了以下代码:

algorithm.hpp

代码语言:javascript
复制
#if !defined(_RICE_ESSENTIA_ALGORITHM_HPP_)
# define _RICE_ESSENTIA_ALGORITHM_HPP_

#include "essentia/algorithm.h"
#include "essentia/streaming/streamingalgorithm.h"

#include "rice/Director.hpp"

namespace Rice
{
  namespace Essentia
  {
    namespace Standard
    {
      class AlgorithmProxy : public essentia::standard::Algorithm, public Rice::Director
      {

        public:
        AlgorithmProxy(Rice::Object self) : Rice::Director(self) {}

        virtual void compute()
        {
          getSelf().call("compute");
        }

        void default_compute()
        {
          raisePureVirtual();
        }

        virtual void reset()
        {
          getSelf().call("reset");
        }

        void default_reset()
        {
          essentia::standard::Algorithm::reset();
        }

        virtual void declareParameters()
        {
          getSelf().call("declare_parameters");
        }

        void default_declareParameters()
        {
          raisePureVirtual();
        }
      };

      void install_algorithm();
    }

    namespace Streaming
    {
      class AlgorithmProxy : public essentia::streaming::Algorithm, public Rice::Director
      {

        public:
        AlgorithmProxy(Rice::Object self) : Rice::Director(self) {}

        virtual essentia::streaming::AlgorithmStatus process()
        {
          return from_ruby<essentia::streaming::AlgorithmStatus>(getSelf().call("process"));
        }

        essentia::streaming::AlgorithmStatus default_process()
        {
          raisePureVirtual();
          return essentia::streaming::AlgorithmStatus::FINISHED;
        }

        virtual void reset()
        {
          getSelf().call("reset");
        }

        void default_reset()
        {
          essentia::streaming::Algorithm::reset();
        }

        virtual void shouldStop(bool stop)
        {
          getSelf().call("should_stop");
        }

        void default_shouldStop(bool stop)
        {
          essentia::streaming::Algorithm::shouldStop(stop);
        }

        virtual bool shouldStop() const
        {
          return from_ruby<bool>(getSelf().call("should_stop?"));
        }

        bool default_shouldStop() const
        {
          return essentia::streaming::Algorithm::shouldStop();
        }

        virtual void declareParameters()
        {
          getSelf().call("declare_parameters");
        }

        void default_declareParameters()
        {
          raisePureVirtual();
        }
      };

      void install_algorithm();
    }
  }
}

#endif /* !defined(_RICE_ESSENTIA_ALGORITHM_HPP_) */

algorithm.cpp

代码语言:javascript
复制
#include "rice/Data_Type.hpp"
#include "rice/Enum.hpp"
#include "rice/Constructor.hpp"

#include "exception.hpp"
#include "modules.hpp"
#include "algorithm.hpp"

namespace Rice
{
  namespace Essentia
  {
    namespace Standard
    {

      static Rice::Data_Type<essentia::standard::Algorithm> standard_algorithm_type;

      void
      install_algorithm()
      {
         RUBY_TRY
         {
           standard_algorithm_type =
             define_class_under<essentia::standard::Algorithm>(essentia_standard_module(), "Algorithm")
             .define_director<AlgorithmProxy>()
             .define_constructor(Rice::Constructor<AlgorithmProxy, Rice::Object>())
             .add_handler<essentia::EssentiaException>(handle_essentia_exception)
             .define_method("reset", &AlgorithmProxy::default_reset)
             .define_method("compute", &AlgorithmProxy::default_compute)
             .define_method("input_names", &AlgorithmProxy::inputNames)
             .define_method("output_names", &AlgorithmProxy::outputNames)
             .define_method("input_types", &AlgorithmProxy::inputTypes)
             .define_method("output_types", &AlgorithmProxy::outputTypes)
             .define_method("declare_parameters", &AlgorithmProxy::default_declareParameters)
             ;
         }
         RUBY_CATCH
      }

    }

    namespace Streaming
    {

      static Rice::Enum<essentia::streaming::AlgorithmStatus> algorithm_status_type;

      void
      install_algorithm_status()
      {
        algorithm_status_type =
          define_enum<essentia::streaming::AlgorithmStatus>("AlgorithmStatus", essentia_streaming_module())
          .define_value("OK", essentia::streaming::AlgorithmStatus::OK)
          .define_value("CONTINUE", essentia::streaming::AlgorithmStatus::CONTINUE)
          .define_value("PASS", essentia::streaming::AlgorithmStatus::PASS)
          .define_value("FINISHED", essentia::streaming::AlgorithmStatus::FINISHED)
          .define_value("NO_INPUT", essentia::streaming::AlgorithmStatus::NO_INPUT)
          .define_value("NO_OUTPUT", essentia::streaming::AlgorithmStatus::NO_OUTPUT)
          ;
      }

      static Rice::Data_Type<essentia::streaming::Algorithm> streaming_algorithm_type;
      typedef void (AlgorithmProxy::*set_should_stop)(bool);
      typedef bool (AlgorithmProxy::*get_should_stop)(void) const;

      void
      install_algorithm()
      {
         RUBY_TRY
         {
           streaming_algorithm_type =
             define_class_under<essentia::streaming::Algorithm>(essentia_streaming_module(), "Algorithm")
             .define_director<AlgorithmProxy>()
             .define_constructor(Rice::Constructor<AlgorithmProxy, Rice::Object>())
             .add_handler<essentia::EssentiaException>(handle_essentia_exception)
             .define_method("reset", &AlgorithmProxy::default_reset)
             .define_method("input_names", &AlgorithmProxy::inputNames)
             .define_method("output_names", &AlgorithmProxy::outputNames)
             .define_method("should_stop", set_should_stop(&AlgorithmProxy::default_shouldStop))
             .define_method("should_stop?", get_should_stop(&AlgorithmProxy::default_shouldStop))
             .define_method("disconnect_all", &AlgorithmProxy::disconnectAll)
             .define_method("process", &AlgorithmProxy::default_process)
             .define_method("declare_parameters", &AlgorithmProxy::default_declareParameters)
             ;
           install_algorithm_status();
         }
         RUBY_CATCH
      }

    }
  }
}

虽然我的Init_代码如下:

init.cpp

代码语言:javascript
复制
#include "modules.hpp"
#include "setup.hpp"
#include "types.hpp"
#include "exception.hpp"
#include "algorithm.hpp"
#include "io.hpp"

extern "C" {

  void Init_essentia_ruby_wrap()
  {
    Rice::Essentia::create_essentia_modules();
    Rice::Essentia::install_essentia_types();
    Rice::Essentia::setup_essentia();
    Rice::Essentia::Standard::install_io();
    Rice::Essentia::Standard::install_algorithm();
    Rice::Essentia::Streaming::install_algorithm();
  }

}

所有东西都编译得很好(使用clang++ -std=c++1y),但是当我试图运行生成的代码时,我会得到:

代码语言:javascript
复制
eeepc-1215B:.../essentia-ruby$ ruby -I./lib/essentia -e "require 'essentia_ruby_wrap'"
/home/nicb/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require': Essentia::Streaming::Algorithm is not a class (Module) (TypeError)
    from /home/nicb/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from -e:1:in `<main>'

我不知道代码中有什么问题,我到处寻找答案,但都没有结果。

我的完整代码是这里

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-09-10 19:59:08

解出

就像我想的那样,这是一件非常愚蠢的事情。

通过查看产生错误的ruby代码,我无意中发现了该解决方案:

C类(第641-660行)

代码语言:javascript
复制
642 VALUE
643 rb_define_class(const char *name, VALUE super)
644 {
645     VALUE klass;
646     ID id;
647 
648     id = rb_intern(name);
649     if (rb_const_defined(rb_cObject, id)) {
650     klass = rb_const_get(rb_cObject, id);
651     if (!RB_TYPE_P(klass, T_CLASS)) {
652         rb_raise(rb_eTypeError, "%s is not a class (%"PRIsVALUE")",
653              name, rb_obj_class(klass));
654     }
655     if (rb_class_real(RCLASS_SUPER(klass)) != super) {
656         rb_raise(rb_eTypeError, "superclass mismatch for class %s", name);
657     }
658     return klass;
659     }

上面写的文件说:

代码语言:javascript
复制
throws a TypeError if the constant name is already taken but
the constant is not a Class.

我突然想到,在尝试模仿ruby约定时,essentia的目录树(因此为每个目录构建了一个模块),我已经创建了一个名为Essentia::Streaming::Algorithm的模块,因此不可能有同名的类。

我可以说,我被一些不同的问题误导了,但我会避免这一点:我太愚蠢了,忘记几天前我已经对这个模块进行了编码--没有任何借口。我们得到的教训是,ruby将不允许同名的moduleclass,只会挑选最先出现的人。这完全合乎逻辑,仅此而已。

票数 0
EN

Stack Overflow用户

发布于 2017-09-08 08:34:26

这将是一个更多的评论,但我把它作为一个回答,为了格式化。如果这是一个错误的假设,请告诉我,这样我就可以删除它。

我相信原因是ruby扩展期望名称空间被大写化,而它们不是。请尝试别名命名空间

代码语言:javascript
复制
namespace Essentia = essentia;
namespace Essentia::Streaming = essentia::streaming;

等等,这会有帮助的。NB我试图克隆回购并自己执行,但是./wav命令(如README中所指定的)失败了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46110074

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档