2010-08-31 6 views
5

için dışa aktarılan işlevde atılan C++ istisnası işleme Uygulamamın Qt komut altyapısını, kullanıcının işlevselliğine erişmesi için alternatif bir yol olarak kullanıyorum. Bu nedenle, bazı C++ sınıflarını uygulamaya arabirim olarak hizmet edecek Qt ScriptEngine'e dışa aktarıyorum. Sorun şu ki, bu C++ sınıfları istisnalar atabilir.QtScript

Kendi iş parçacığımda çalışan komut dosyalarını işlemek için istekleri dinleyen bir "ScriptInterface" sınıfım var. Dolayısıyla, bir kullanıcının betiğini değerlendirdiğimde, istisnaları işlemek için bir deneme/yakalama bloğum var ve hatayı uygulamadaki konsolda yazdırıyorum. Ben istisnalar için köpürdü çünkü olduğuna dair bir his vardı

terminate called after throwing an instance of 'Basilisk::InvalidArgumentException' 
    what(): N8Basilisk24InvalidArgumentExceptionE 
Aborted 

:

... 
try { 
    m_engine->evaluate(script, name); 
} 
catch (Exception const& e) { 
    // deal with it 
} 
catch (...) { 
    // scary message 
} 

Bu pencerelerde mükemmel çalışıyor ... ama programa linux- çalışmıyor bu mesajla sona erer olay işleyicisi (komut dosyası altyapısı, dışa aktarılan sınıflarımdaki işlevleri çağırmak için sinyaller kullandığı için), bu nedenle, istisnaları işlemek için QApplication :: notify'ı yeniden yapılandırdım, ancak yakalanmadılar.

Sorum şu ki, temelde yanlış bir şey yapıyorum? Ayrıca, alternatif olarak, C++ sınıflarımdan komut dosyası istisnalarını açıkça atamak mümkün mü? peşin

DÜZENLEME içinde

Teşekkür: catch (...) deyimi içerecek şekilde açıklama sabit.

GÜNCELLEME (ÇÖZÜM): kabul edilen yanıt özetlenen benzer bir strateji izleyerek Ben "sabit" Bu sorunu. Her ne kadar istisnaların linux'a yakalanmamasının kaynağına gitmemiş olsam da (şüphe şuyum, m_engine-> linux üzerinde ayrı bir iş parçacığı ürettiğidir), ama ben amaçlanan yolunu kullanmaya başladım. Qt Scripts içinde istisna, ve bu QScriptContext::throwError(). Benim işlevi şu şekilde görünecektir durumlarda

:

QScriptValue SomeClass::doStuff(unsigned int argument) { 
    if (argument != 42) { 
     // assuming m_engine points to an instance of 
     // QScriptEngine that will be calling this function 
     return m_engine->currentContext()->throwError(QScriptContext::SyntaxError, 
      "Not the answer to Life, the Universe and Everything."); 
    } 


    try { 
     // function that is not part of the scripting environment, 
     // and can throw a C++ exception 
     dangerousFunction(argument); 
    } catch (ExpectedException const& e) { 
     return m_engine->currentContext()->throwError(QScriptContext::UnknownError, 
      e.message()); 
    } 

    // if no errors returned, return an invalid QScriptValue, 
    // equivalent to void 
    return QScriptValue(); 
} 

(dönüş türüne özellikle dikkat) Peki birini yapar: (rastgele örnek)

void SomeClass::doStuff(unsigned int argument) { 
    if (argument != 42) { 
     throw InvalidArgumentException(
      "Not the answer to Life, the Universe and Everything."); 
    } 

    // function that is not part of the scripting environment, 
    // and can throw a C++ exception 
    dangerousFunction(argument); 
} 

Şimdi bu Bu script hataları ile başa çıkmak? QScriptEngine::evaluate() numaralı çağrıdan sonra, QScriptEngine::hasUncaughtException() ile yakalanmamış istisnalar olup olmadığını kontrol edebilir, uncaughtException() ile hata nesnesini elde edebilirsiniz ve şimdi, hatanın oluştuğu komut dosyasında iletiye, ize ve satır numarasına sahipsiniz!

Bunun birilerine yardım edeceğini umarız!

+0

var mı uygulanıyor [istisna belirtimleri] ile işlev (http://www.gotw.ca/publications/mill22.htm) dahil? –

+0

değil her yerde 'catch (...) mu –

+0

benim sınıflarında {}' bu istisnayı da yakalayabilir? – tibur

cevap

3

C++ kitaplıklarını sarmak için SWIG with Python kullanmaya çalışırken benzer türde bir soruna rastladım. Sonunda olanlar, istisnai yakalanan ve sessizce başarısız olan bütün sarılı sınıflar için bir saplama yaptım. Neyse ki, kapsayıcı sınıfları ve durum desen nesnelerini geçiren sarma işlevinin lüksüne sahip oldum, böylece bir şeylerin yanlış olup olmadığını kolayca kontrol edebildim. Senin için aynısını önerebilir miyim?

  1. İstediğiniz işlevleri başka bir işlevle, geri dönüş değeri dışında aynı arabirimle sarın.
  2. istenen dönüş türü değil, aynı zamanda bir hata göstergesi sadece içeren bir nesne oluşturun.
  3. komut istisnalar kontrol etmek için emin olun var.

Ve bunu bir istisna fabrikasına erişimi verdiyseniz evet, C++ istisnalar atmak için bir komut dosyası motoru için çok mümkün (Tek amacı C++ istisnalar atmak olan bir sınıfın.)

+1

Süper geç kabul, ancak bu hafta bu probleme geri döndüm ve temel olarak anlattığın şeye çok benzer bir şey yaptım. Özel durumum için çözümümün gösterilmesi için yayınımı düzenlerim. Teşekkürler! –

1

Programınızı bir hata ayıklayıcısında çalıştırın ve çalışma zamanı kitaplığınızın terminate() işlevinin içine bir kesme noktası yerleştirin. Bu şekilde, hata ayıklayıcıda terminate() üzerinde duracaksınız ve çağrı yığınını denetleyerek, terminate() çağrısının nereden yapıldığını göreceksiniz.