Qore dual class 实现(C++/Qore)和从 C++ 核心调用虚方法

Qore dual class implementation (C++/Qore) and calling virtual method from C++ core

我需要在 C++ 中实现 class QoreFoo 并通过 .qpp 实现 Qore 脚本 Foo 的双重实现。 QoreFoo 是抽象的 class 提供通用 API 并且真正的功能将被添加到 descendand class (在 C++ 或 Qore 中)。来自核心 i.e.C++ 的 Foo API 调用需要传播到实例化对象,无论在何处使用后代 class。

QoreFoo.h

# implement general API

class QoreFoo {
public:
  virtual void bar(ExceptionSink *xsink)=0; 
};

extern QoreFoo* current_foo;

// just assign instance of a descendant of QoreFoo 
void QoreAssignFoo(QoreFoo* n_foo) {
  current_foo = n_foo;
}

QoreFoo.cpp

QoreFoo* current_foo = 0;

any.cpp

if (current_foo)
  current_foo.bar(xsink);  // propagate call via overriden method

当我需要实现简单的 C++ 后代时:

QoreFoo2.h

class QoreFoo2: QoreFoo {
  void bar(ExceptionSink *xsink) {
    # my stuff
    printf("Hello World from C++");
  }
};

usage.cpp

QoreAssignFoo(new QoreFoo2);
# wait for "Hello World from C++" when core calls current_foo.bar()
.....

但是如何传播对 Qore 脚本的调用 class? 我认为需要额外的 class 来调用 dual class 在 .qpp 中定义并在 .q

中覆盖

QoreFooHelper.h

class QoreFooHelper: class QoreFoo {
private:
  QoreObject* qo;
public:
  QoreFooHelper(QoreObject* n_qo): qo(n_qo) {
  }
  void bar(ExceptionSink *xsink) {
    // convert args if any
    // call virtual function of Foo class, i.e. qo 
    qo->evalMethod("bar", 0, xsink);
  }

QC_Foo.qpp

# implement assign instance function
nothing assignFoo(*Foo foo) {
  QoreAssignFoo(foo->p);
}

#implement class for Qore script
qclass Foo [arg=QoreFooHelper* p]

Foo::constructor() {
  assert(self->validInstanceOf(CID_FOO));   // is it correct test to test if inherited from ?
  QoreFoo* f = new QoreFooHelper(self);
  self->setPrivate(CID_FOO, f);
}

# probably useless as it generates function code
#nothing Foo::bar() {
#}

Test.q

class Foo2 inherits Foo {
  nothing bar() {
    # my stuff
    printf("Hello world from Q");  
  }
}

Foo2 foo();
assignFoo(foo);  # assign instance of Foo2
# wait for "Hello World from Q" message when core calls current_foo.bar()
....

这是可行的解决方案还是确实存在更好的方法,例如使用 qpp 功能或避免 QoreFooHelper(但在 C++ 中完全实现 QoreFoo2 时我需要避免开销)?

如果不是,那么替代选项是什么,例如以某种方式传递 callref 或闭包并进行真正的回调?

编辑:

在 .qpp 中定义 Qore class 时 qpp 生成 class 定义 QoreClass* initFoo() (添加方法、构造函数等)并将其注册到命名空间存储库中。

当要创建新的 QoreObject 时,将使用 QoreClass 作为参数在命名空间 repo 中找到。

.qpp 定义的构造函数通常创建纯 C++ QoreFoo 实例并分配为私有 属性 (self->setPrivate(CID_FOO , new QoreFoo())), 即link from Foo to QoreFoo 成立, 将在定义 .qpp 方法,其中使用纯 C++ 操作。 .qpp 将适当的 C++ 代码生成到函数 "header" 中。 selfQoreObject 实例。

我认为 Foo3 脚本 class 在运行时也是如此。

Qpp 帮助实现 Qore 东西来调用 C++ 东西。

但我需要相反的方向,从 C++ 调用 Qore 方法,所以我想我需要调用 QoreObject::evalMethod()。由于 QoreObject 不 存在于普通 C++ class 中,因此需要额外的后代 QoreFooHelper 来实现它(将一般对象作为参数传递时会出现额外问题)。

如果您要执行的 API 是 Qore-language class API,那么您需要在 Qore 中实现抽象 class 而不是在 C++ 中。

如果你有一个 C++ 虚拟 class 层次结构应该在 Qore 中扩展,那么你应该使用 qpp 在 C++ 中实现你的 Qore class 然后允许程序员通过 sub 自然地扩展它class在 Qore 中 classes。

你可以这样做:

QoreFoo.h

class QoreFoo {
public:
     DLLLOCAL QoreFoo(QoreObject* o) : obj(o) {
     }
     // other functions...
private:
     QoreObject* obj;  //!< The QoreObject this private data is associated with
};

QC_Foo.qpp

//! This class defines an abstract interface for ...
/**
 */
qclass Foo [arg=QoreFoo* foo; ns=Foo];

//! Constructor
/** Used by subclasses defined in Qore
 */
Foo::constructor() {
    self->setPrivate(CID_FOO, new QoreFoo(self));
}

//! a method to ...
/**
 */
abstract nothing Foo::bar();

这允许 class Foo 有一些私有数据和一个抽象的 Qore API 可以被 subclasses 使用; C++ 中的 subclasses(使用 qpp 实现)应将 Foo 声明为 vparent,如下例所示:

QoreFoo2.h

#include "qore/intern/QoreFoo.h"

class QoreFoo2 : public QoreFoo {
public:
     DLLLOCAL QoreFoo2(QoreObject* o) : QoreFoo(o) {
     }

     DLLLOCAL void bar(ExceptionSink* xsink) {
         printf("Hello World from C++");
     }

     // other functions...
};

QC_Foo2.qpp

#include "qore/intern/QoreFoo2.h"

//! This class ...
/**
 */
qclass Foo2 [arg=QoreFoo2* foo; ns=Foo; vparent=Foo];

//! Constructor
/** Used by subclasses defined in the Qore programming language.
 */
Foo2::constructor() {
    self->setPrivate(CID_FOO2, new QoreFoo2(self));
}

//! a method to ...
/**
 */
nothing Foo2::bar() {
    foo->bar();
}

Foo class 也可以直接在 Qore 中以同样的方式子classed:

class Foo3 inherits Foo {
    bar() {
        print("Hello world from Q");
    }
}

编辑

@TMa 如果你想从 C++ 调用一个 Qore-language 方法,那么使用 QoreObject::evalMethodValue() 正如已经提到的那样 - 你是对的,qpp 不会为你生成这个代码。

如果您想确保该方法在继承父 class 的任何 Qore-language class 中实现,请确保在您的 qpp 中定义抽象 Qore 方法定义父级的文件 class.