2009-11-11 21 views
1

解決方案可能很簡單。然後再次這可能是不可能的。QtScript - 通過C++端實現腳本端回調

我有基本的回調類:

class CFCallback { 
    int command_; 
    int transfer_rate_; 
    public: 
    CFCallback(int command, int transfer_rate = 0) { 
     command_ = command; transfer_rate_ = transfer_rate; } 
    virtual ~CFCallback() {} 
    virtual void operator()(void *data) = 0; 
    int GetCommand() { return command_; } 
    int GetTransferRate() { return transfer_rate_; } 
}; 

下面是從CFCallback得出的一個例子:

void CFPacketVersion::InitiateVersion() { 
    class InitiateVersionCB : public CFCallback { 
     CFPacketVersion *visitor_; 
     public: 
     InitiateVersionCB(CFPacketVersion *v, int command) : 
      CFCallback(command) { 
      visitor_ = v; 
     } 
     void operator()(void *data) { 
      Packet *pkt = (Packet *)data; 
      unsigned char *pkt_data = pkt->GetData(); 
      std::string version = ""; 
      for(unsigned int i = 0; i < pkt->GetDataLength(); i++) 
       version+= pkt_data[i]; 
      delete []pkt_data; 
      boost::regex rex("CFA(.*?):h(.*?),v(.*?)$"); 
      boost::smatch what; 
      if(boost::regex_match(version, what, rex)) { 
       if(visitor_->GetModel()->GetName() != what[1].str()) 
        LCDInfo("Crystalfontz: Model mismatch"); 
       visitor_->SetHardwareVersion(what[2]); 
       visitor_->SetFirmwareVersion(what[3]); 
      } 
     } 
    }; 
    GetVersion(new InitiateVersionCB(this, 1)); 
} 

GetVersion(CFCallback *)提供給腳本引擎。

我希望能夠做到InitiateVersion中看到的同樣的事情,但在javascript的一面。那可能嗎?

我知道我需要註冊meta型信息CFCallback。但我不知道是否可以使用指向CFCallback的指針。我最初試過的東西沒有用。

此外,看到CFCallback是一個仿函數,我不知道如何將它翻譯爲JavaScript。我想我可以讓CFCallback a QObject並提供從operator()發出的信號。如果您有任何提示,請分享。

回答

2

恐怕它不會按照您設置的方式工作。

如果您希望能夠在javascript中創建回調,您需要帶有可訪問的GetVersion(QScriptValue)的QObject,腳本將使用該QObject來傳遞基於腳本的回調實現。但是,請注意,回調將無法使用無類型(void *)數據 - 您需要傳遞有效的QtScript對象或QObject與適當的接口(如您的示例中的數據包一樣!)

然後,您可以把它包起來是這樣的:

QtScript:

function mycb(packet) { 
    var pkt_data = packet.getData(); // pkt_data is probably a String or custom object with proper interface so to simplify things get the version as string 
    var version = pkt_data.toString(); 
    pkt_data.release(); // to simulate delete [] pkt_data; this is part of custom interface 
    // proceed further with the regex checks 

} 

GetVersion(mycb); // implies that you define the GetVersion() as a property of the global object 

C++:

QScriptValue getVersion(QScriptContext *ctx, QScriptEngine *engine) 
{ 
void *data = ...; 
Packet pkt_data = wrapPacketData(data); 
// Packet is interface registered with QtScript or inherits QObject 
// it has methods getData(), toString() and release() 
QScriptValueList args; 
QScriptValue pkt_data_param = engine->newQObject(&pkt_data); 
args << pkt_data_param; 
QScriptValue cb = ctx->argument(0); 
Q_ASSERT(cb.isFunction()); // we expect a function object! 
cb.call(QScriptValue(), args); 
} 
QScriptValue getVersionFun = engine->newFunction(getVersion); 
engine->globalObject().setProperty(QLatin1String("GetVersion"), getVersionFun);