2010-08-31 24 views
5

Tôi đang sử dụng công cụ tập lệnh Qt trong ứng dụng của mình như một cách thay thế để người dùng truy cập chức năng của nó. Như vậy, tôi xuất một số lớp C++ sang Qt ScriptEngine, nó sẽ là giao diện cho ứng dụng. Vấn đề là, các lớp C++ có thể ném ngoại lệ.Xử lý ngoại lệ C++ được ném vào hàm được xuất sang QtScript

Tôi có một lớp "ScriptInterface" chạy trên chuỗi riêng của mình, lắng nghe các yêu cầu xử lý tập lệnh. Vì vậy, khi tôi đánh giá kịch bản của người dùng, tôi có một khối try/catch xung quanh nó để xử lý các trường hợp ngoại lệ, và in lỗi tới bàn điều khiển trong ứng dụng.

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

này hoạt động hoàn hảo trong các cửa sổ ... nhưng không hoạt động trong linux- chương trình kết thúc với thông điệp này:

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

Tôi đã có một linh cảm rằng đó là vì các trường hợp ngoại lệ sôi nổi xử lý sự kiện (vì công cụ script sử dụng các tín hiệu để gọi các hàm trong các lớp đã xuất của tôi), vì vậy tôi đã thực hiện lại QApplication :: thông báo, để xử lý các ngoại lệ ở đó, nhưng chúng không bị bắt.

Câu hỏi của tôi là, tôi đang làm điều gì đó sai về cơ bản? Ngoài ra, như là một thay thế, là nó có thể rõ ràng ném ngoại lệ kịch bản từ bên trong lớp C++ của tôi?

Cảm ơn trước

EDIT: sửa mô tả để bao gồm câu lệnh bắt (...).

CẬP NHẬT (GIẢI PHÁP): Tôi "cố định" vấn đề này bằng cách làm theo một chiến lược tương tự như chiến lược được nêu trong câu trả lời được chấp nhận. Mặc dù tôi đã không đi đến nguồn gốc của lý do tại sao các trường hợp ngoại lệ không bị bắt trên Linux (nghi ngờ của tôi bây giờ, là m_engine-> đánh giá đẻ trứng một thread riêng biệt trên linux), nhưng tôi đã bắt đầu sử dụng dự định cách ngoại lệ ném trong Tập lệnh Qt, và đó là QScriptContext::throwError().

Trong trường hợp chức năng của tôi sẽ trông như thế này: (ví dụ ngẫu nhiên)

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

Nó bây giờ là thế này: (đặc biệt chú ý đến kiểu trả về)

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

Vì vậy, nơi nào một đối phó với các lỗi tập lệnh này? Sau khi gọi tới QScriptEngine::evaluate(), bạn có thể kiểm tra xem có bất kỳ ngoại lệ không bị bắt buộc nào, với QScriptEngine::hasUncaughtException(), lấy đối tượng lỗi với uncaughtException() và bây giờ bạn có thông báo, dấu vết và số dòng trong tập lệnh có lỗi xảy ra!

Hy vọng điều này sẽ giúp ai đó ra ngoài!

+0

Có chức năng với [đặc tả ngoại lệ] (http://www.gotw.ca/publications/mill22.htm) có liên quan? –

+0

Không phải bất kỳ nơi nào trong lớp học của tôi –

+0

Có 'catch (...) {}' bắt ngoại lệ đó không? – tibur

Trả lời

3

Tôi đã gặp phải một loại vấn đề tương tự khi cố gắng sử dụng SWIG với Python để bọc các thư viện C++. Cuối cùng những gì đã xảy ra là tôi đã thực hiện một bài sơ khai cho tất cả các lớp học bọc mà bắt được ngoại lệ và thất bại lặng lẽ. May mắn thay, tôi đã có một chức năng gói bọc sang trọng mà chỉ thông qua các lớp container và các đối tượng mẫu trạng thái, vì vậy tôi có thể dễ dàng kiểm tra xem có điều gì đó không ổn. Tôi có thể đề xuất tương tự cho bạn không?

  1. Bỏ các chức năng bạn muốn bằng chức năng khác, cùng giao diện ngoại trừ giá trị trả về.
  2. Tạo một đối tượng không chỉ chứa kiểu trả về được yêu cầu mà còn là chỉ báo lỗi.
  3. Có tập lệnh đảm bảo kiểm tra các ngoại lệ.

Và vâng, nó rất có thể cho một công cụ script để ném ngoại lệ C++ nếu bạn đã cho nó truy cập vào một nhà máy ngoại lệ (một lớp học với mục đích duy nhất là để ném ngoại lệ C++.)

+1

Super late chấp nhận, nhưng tôi đã trở lại vấn đề này trong tuần này và về cơ bản đã làm một cái gì đó rất giống với những gì bạn mô tả. Tôi sẽ chỉnh sửa bài đăng của mình để hiển thị giải pháp cho trường hợp cụ thể của tôi. Cảm ơn! –

1

Chạy chương trình của bạn trong trình gỡ rối và đặt điểm ngắt bên trong hàm terminate() của thư viện thời gian chạy của bạn. Bằng cách đó bạn sẽ dừng lại trên chấm dứt() trong trình gỡ lỗi và bằng cách kiểm tra ngăn xếp cuộc gọi, bạn sẽ thấy từ đó chấm dứt() được gọi.

Các vấn đề liên quan