2017-02-17 51 views
2

虛擬方法我需要實現一個類QoreFoo在C++,並經由.qpp其雙重實施Qore腳本。 QoreFoo是提供通用API的抽象類,真正的功能將被添加到descend和class(C++或Qore)中。來自內核的Foo API調用(即C++)需要傳播到實例化對象,而不管使用何種後代類。Qore雙類實現(C++/Qore)並調用從C++芯

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 

當我需要impleme NT 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腳本類?我覺得需要一個額外的類中調用.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(但我需要避免開銷時完全實施QoreFoo2在C + +)?

如果不是那麼什麼是替代選項,例如,以某種方式傳遞callref或閉包,並做真正的回調?

編輯:

當.qpp定義Qore類然後QPP生成類定義QoreClass * initFoo()(添加方法,構造等),並將其登記到一個命名空間信息庫。

當新QoreObject要然後,創建被構造有QoreClass如在名稱空間回購發現參數。

.qpp定義的構造通常會創建純C++ QoreFoo實例並分配私有財產(自> setPrivate(CID_FOO,新QoreFoo())),即,從富鏈路QoreFoo建立並將在定義.qpp方法時使用,其中使用純C++的東西進行操作。 .qpp生成適當的C++代碼到函數「header」中。 self is QoreObject instance。

我認爲同樣在運行時爲Foo3腳本類。

Qpp幫助實現Qore的東西來調用C++的東西。

但我需要相反的方向,從C++調用Qore方法,所以我認爲我需要調用QoreObject :: evalMethod()。由於QoreObject不存在 ,所以需要額外的後代QoreFooHelper來實現它(在將常規對象作爲參數傳遞時,會帶來額外的問題)。

回答

3

如果您要強制執行的API是Qore語言類API,那麼您需要在Qore中實現抽象類,而不是在C++中實現。

如果您有一個應該在Qore中擴展的C++虛擬類層次結構,那麼您應該使用qpp在C++中實現您的Qore類,然後允許程序員通過在Qore中繼承您的類來自然擴展它。

你可以這樣說:

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(); 

這允許類Foo有一些私人數據和抽象Qore API可以被子類使用;在C++(以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類,直接可以在子類中Qore以同樣的方式:

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

編輯

@TMa如果你要調用一個Qore語言的方法從C++,然後使用QoreObject::evalMethodValue()已經提到 - 你是對的,qpp不會爲你生成這個代碼。

如果要確保該方法在任何繼承父類的Qore語言類中實現,請確保在定義父類的qpp文件中定義抽象Qore方法。

+0

* current_foo *是對象的實際實例* QoreFoo *實現請求的功能。是的,線程安全必須實現,但它只是一個例子。 * qo-> evalMethod(「bar」,0,xsink); * – TMa

+0

我的想法是從C++調用* Foo :: bar * virtual方法是否正確?我雖然關於QoreFooHelper來做到這一點。這個類將被用作所有qore腳本* FooXXX *類的父類。當使用普通的C++東西(char,class,pointer等)在C++中將fetaure完全實現爲二進制模塊時,它將直接下降* QoreFoo *。 – TMa

+1

@TMa似乎有一些基本的誤解 - 'self'是當前的Qore對象,它作爲參數傳遞給實現該方法的C++函數中的每個非靜態Qore方法(即由qpp生成的那個)實現所需邏輯的C++對象需要作爲構造函數中的私有數據附加到'QoreObject'('self')。然後調用在私有數據對象上實現方法對象的C++函數(該函數也作爲參數傳遞給C++函數)。 –