NS2 시작 자습서-Tcl 클래스

5474 단어
여기 ~/tclcl/tclcl에 대해 설명해 드리겠습니다.h에 봉인된 OTcl 해석기의 실제 실례와 이 해석기에 접근하여 통신하는 방법을 제공합니다.
Tcl 클래스는 다음과 같은 방법을 제공합니다.
  • Tcl 객체에 대한 참조 획득
  • OTcl의 함수를 호출하여 해석기
  • 를 통해
  • 해석기에 대한 값 또는 전송
  • 오류 보고 및 일관된 방식으로 종료
  • TclObjects를 저장하고 찾습니다.
  • 해석기에 대한 직접 접근 획득
  • 각 방법에 대한 자세한 내용은 다음과 같습니다.

    Tcl 객체에 대한 참조 가져오기


    이 클래스의 단일 인스턴스는 ~tclcl/Tcl에 있습니다.cc에서 정적 구성원 변수로 성명하기;
    우리는 이 실례에 대한 인용을 받아야만 이 절에서 기술한 다른 방법에 접근할 수 있다.
    이 인스턴스에 액세스하는 데 필요한 문은 다음과 같습니다.
    Tcl& tcl = Tcl::instance();
    

    OTcl 함수를 호출하여 해석기를 통해


    인스턴스 tcl을 통해 OTcl 명령을 호출하는 방법에는 네 가지가 있습니다.그것들의 매개 변수는 기본적으로 다르다.
    모든 함수는 하나의 문자열을 해석기에 전달하고 전체 상하문에서 문자열의 의미를 평가한다.
  • 해석기가 TCL을 반환하는 경우OK, 이러한 방법은 호출자에게 돌아갑니다.
  • 다른 한편, 해석기가 TCL 을 반환하는 경우ERROR - 메서드는 tkerror 오류를 보고합니다.사용자는 이 과정을 다시 불러와서 일부 유형의 오류를 선택적으로 무시할 수 있습니다.
  • void Tcl::evalc(const char* s)
    {
        unsigned int n = strlen(s) + 1;
        if (n < sizeof(buffer_) - (bp_ - buffer_)) {
            char* const p = bp_;
            bp_ += n;
            strcpy(p, s);
            eval(p);
            bp_ = p;
        } else {
            char* p = new char[n + 1];
            strcpy(p, s);
            eval(p);
            delete[] p;
        }
    }
    
    void Tcl::eval(char* s)
    {
        int st = Tcl_GlobalEval(tcl_, s);
        if (st != TCL_OK) {
            int n = strlen(application_) + strlen(s);
            if (n > MAX_CODE_TO_DUMP) {
                s = "
    [code omitted because of length]
    "; n = strlen(application_) + strlen(s); }; char* wrk = new char[n + 80]; sprintf(wrk, "tkerror {%s: %s}", application_, s); if (Tcl_GlobalEval(tcl_, wrk) != TCL_OK) { fprintf(stderr, "%s: tcl error on eval of: %s
    ", application_, s); exit(1); } delete[] wrk; //exit(1); } } void Tcl::eval() { char* p = bp_; bp_ = p + strlen(p) + 1; /*XXX*/ if (bp_ >= &buffer_[1024]) { fprintf(stderr, "bailing in Tcl::eval
    "); assert(0); exit(1); } eval(p); bp_ = p; } /* * , 4 , evalf, Tcl.cc , * , , * */

    다음 예제에서는 이러한 함수를 호출합니다.
    Tcl& tcl = Tcl::instance();
    char wrk[128];
    strcpy(wrk, "Simulator set NumberInterfaces_ 1");
    tcl.eval(wrk);
    
    sprintf(tcl.buffer(), "Agent/SRM set requestFunction_ %s", "Fixed");
    tcl.eval();
    
    tcl.evalc("puts stdout {hello world}");
    
    tcl.evalf("%s request %d %d", name_, sender, msgid);
    

    해석기에 값을 얻거나 전달합니다


    해석기가 C++ 방법을 호출할 때, 결과를 개인 구성원 변수 tcl ->로 되돌려줍니다result에 있습니다.
    이 변수를 설정하는 데 두 가지 방법이 있습니다.(to)
    void result(Tcl_Obj *pObj) { 
        Tcl_SetObjResult(tcl_, pObj); 
    }
    
    inline const char* result() const { 
        return (char *) Tcl_GetStringResult(tcl_); 
    }
    
    inline char* result() const {
        return (tcl_->result); 
    }
    
    inline void result(const char* p) { 
        tcl_->result = (char*)p; 
    }
    
    void resultf(const char* fmt, ...);
    
    /*examples*/
    
    if (strcmp(argv[1], "now") == 0) {
        tcl.resultf("%.17g", clock());
        return TCL_OK;
    }
    tcl.result("Invalid operation specified");
    return TCL_ERROR;
    

    마찬가지로, C++ 방법이 OTcl 명령을 호출할 때, 해석기는 tcl ->result에서 결과를 되돌려줍니다.(from)
    tcl.evalc("Simulator set NumberInterfaces_");
    char* ni = tcl.result();
    if (atoi(ni) != 1)
        tcl.evalc("Simulator set NumberInterfaces_ 1");
    

    오류 보고 및 일관된 방식으로 종료


    이 방법은 컴파일된 코드의 오류를 보고하는 통일된 방법을 제공했다.
    void Tcl::error(const char* s)
    {
        if (strlen(s) > MAX_CODE_TO_DUMP) {
            s = "
    [code omitted because of length]
    "; }; fprintf(stderr, "%s: \"%s\": %s
    ", application_, s, tcl_->result); exit(1); } /* example */ tcl.resultf("cmd = %s", cmd); tcl.error("invalid command specified");

    주의: Tcl::result와 Tcl:::error를 호출하는 것은 약간의 차이가 있습니다. 리셋 오류를 호출하면 해석기가 이상을 포착하고, 동시에 창고의 추적을 되돌려줍니다. 오류를 수정하기 위해 디버깅을 할 수 있지만, error를 사용하면 창고의 추적을 되돌려주지 않습니다.

    TclObjects 저장 및 찾기


    NS2는 컴파일 계층의 각 TclObject에 대한 참조를 해시 테이블에 저장합니다.이렇게 하면 객체에 빠르게 액세스할 수 있습니다.
    해시표는 해석기의 내부다.NS2는 TclObject의 이름을 키로 사용하여 해시 테이블에 입력하고 TclObject를 찾거나 삭제합니다.
    void Tcl::enter(TclObject* o)
    {
        int nw;
        Tcl_HashEntry* he = Tcl_CreateHashEntry(&objs_, (char*)o->name(),
                            (int*)&nw);
        Tcl_SetHashValue(he, (char*)o);
    }
    /*
     *      insert a pointer to the TclObject into hashtable
     */
    
    TclObject* Tcl::lookup(const char* name)
    {
        /*XXX use tcl hash table */
        Tcl_HashEntry* he = Tcl_FindHashEntry(&objs_, (char*)name);
        if (he != 0)
            return ((TclObject*)Tcl_GetHashValue(he));
        return (0);
    }
    /*
     *      retrieve the TclObject with the name
     */
    
    void Tcl::remove(TclObject* o)
    {
        Tcl_HashEntry* he = Tcl_FindHashEntry(&objs_, (char*)o->name());
        if (he == 0)
            abort();
    
        Tcl_DeleteHashEntry(he);
    }
    /*
     *      delete references to the TclObject from the hash table
     */
    

    이러한 함수는 클래스 TclObject와 클래스 TclClass가 내부에서 사용합니다.

    해석기에 대한 직접 접근 얻기


    만약 위의 방법이 부족하다면, 우리는 해석기의 핸들을 가져와, 우리의 함수를 작성해야 한다.
    inline Tcl_Interp* interp() const { return (tcl_); }
    
    /*
     *      returns the handle to the interpreter that is stored within the class Tcl.
     */
    

    좋은 웹페이지 즐겨찾기