2017-01-28 11 views
2

Embeddable Common Lispをライブラリに埋め込む作業をしています。ECLのcl_objectをさまざまなC/C++型に変換するユーティリティ関数を作成しています。文字列を表すcl_objectをstd :: stringに変換します。ECLのシンボル名をC++の文字列として取得する

私の質問はこれです - なぜECLのシンボル名を含む文字列を取得できませんでしたか?

私はトラブルECLのシンボルを取ると、それの名前でのstd ::文字列を返すべき、動作するように次の関数ecl_symbol_to_stringを取得して抱えている:lispの文字列の

string ecl_symbol_to_string(cl_object sym) { 
    return ecl_string_to_string(sym->symbol.name); 
} 

string ecl_string_to_string(cl_object echar) { 
    string res(""); 
    int j = echar->string.dim; //get dimension 
    ecl_character* selv = echar->string.self; //get pointer 

    //do simple pointer addition 
    for(int i=0;i<j;i++){ 
     res += (*(selv+i)); 
    } 
    return res; 
}; 

ecl_string_to_stringその作品を。

単純なユニットテストが失敗したことを示す:

TEST_CASE("ecl_symbol_to_string returns a string for symbol", 
      "[ecl_string_to_string]") { 

    LispRuntime *rt = new LispRuntime("()"); 
    std::string eval_script; 
    cl_object eval_result; 
    std::string subject_result; 

    eval_script = "'mysymbol"; 
    eval_result = rt->evaluate(eval_script); 
    REQUIRE(ECL_SYMBOLP(eval_result)); 
    subject_result = ecl_symbol_to_string(eval_result); 
    REQUIRE (ECL_STRINGP(cl_symbol_name(eval_result))); 
    std::cout << subject_result.c_str() << std::endl; 
    REQUIRE(subject_result.compare("mysymbol") == 0); 

    delete rt; 

} 

このテストケースはCOUTへの呼び出しのためMMをプリントアウト。私はまた失敗した "MYSYMBOL"と合格した "M"と比較しようと試みました。

LispRuntime :: eval_scriptは、単に形式を変換し、評価:

cl_object LispRuntime::evaluate(std::string &code) { 
    cl_object form = c_string_to_object(code.c_str()); 
    cl_object result = cl_eval(form); 

    return result; 
} 

私はC++のオプションを使用してローカルにECLバージョン16.1.3をコンパイルはデバッグシンボルで、他のすべての設定がデフォルトで有効。どんな支援も大歓迎です。

答えて

3

私はこれがユニコード/ノンユニコードのミックスアップであると信じています:ECLはobject.hに2つの文字列タイプを定義しています。 1つはecl_base_stringであり、メンバーselfは最終的にunsigned char*に型定義され、もう1つはecl_stringであり、メンバーself(通常はコンパイル時引数に依存します)型定義はint*になります。あなたはecl_stringとしてアクセスしています。

ecl_make_symbolの動作をトレースすると、基本文字列を返す関数make_constant_base_stringが呼び出されます。したがって、ecl_string_to_stringは間違ったタイプでアクセスします。

私は、最も簡単な解決策はecl_string_to_stringに型チェック/変換を構築することである疑いがある:

string ecl_string_to_string(cl_object echar) { 
    switch (ecl_t_of(echar)) { 
    #ifdef ECL_UNICODE 
     case t_string: 
     if (!ecl_fits_in_base_string(echar)) { 
      echar = cl_copy_seq(echar); 
     } else { 
      echar = si_copy_to_simple_base_string(echar); 
     } 
     break; 
    #endif 
     case t_base_string: 
     // OK 
     break; 
     default: 
     // PRINT SOME ERROR 
     return string(); // or raise an exception 
    } 

    string res(""); 
    int j = echar->base_string.dim; //get dimension 
    ecl_base_char* selv = echar->base_string.self; //get pointer 

    //do simple pointer addition 
    for(int i=0;i<j;i++){ 
     res += (*(selv+i)); 
    } 
    return res; 
}; 

私が追加した余分なコードが重くECL機能cl_make_symbolからコピーされました。私はecl_stringではなくecl_base_stringに変換することを決めました。なぜなら、C++文字列はUnicode文字を受け入れないからです。もしあなたが正当な理由があれば、おそらく他の方法でそれを行うことができます。

+1

私は現時点でテストするのが簡単ではないので、現在はテストされていないのではないかと心配しています。間違っている可能性があります。申し訳ありませんが、その場合は... – DavidW

+0

これは、実際に書かれた問題を解決し、さらに関連する内部についての洞察を提供するので、私はさらに自分自身で研究することができます。この答えに感謝します。 – Chazu

関連する問題