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" 中。 self 是 QoreObject 实例。
我认为 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.
我需要在 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" 中。 self 是 QoreObject 实例。
我认为 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.