我正试图进入嵌入C++中的Common这个迷人的世界。我的问题是,我无法从c++读取和打印由ECL中定义的lisp函数返回的字符串。
在C++中,我有一个函数来运行任意的Lisp表达式:
cl_object lisp(const std::string & call) {
return cl_safe_eval(c_string_to_object(call.c_str()), Cnil, Cnil);
}我可以用这样的方式用一个数字来做:
ECL:
(defun return-a-number () 5.2)在C++中阅读和打印:
auto x = ecl_to_float(lisp("(return-a-number)"));
std::cout << "The number is " << x << std::endl;所有的东西都设置好了,工作得很好,但我不知道用字符串代替数字。这就是我尝试过的:
ECL:
(defun return-a-string () "Hello")C++:
cl_object y = lisp("(return-a-string)");
std::cout << "A string: " << y << std::endl;打印字符串的结果是:
A字符串: 0x3188b00
我猜是字符串的地址。
这里是调试器和y cl_object内容的捕获。自我类型是一个ecl_character。
调试
发布于 2016-03-17 09:27:25
(从@coredump的回答string.self字段提供结果开始。)
string.self字段被定义为类型ecl_character* (ecl/object.h),它在ecl/config.h中被定义为int类型(尽管我怀疑这与平台有一定的关系)。因此,您将不能像打印字符数组一样只打印它。
我发现我的工作方式是将它重新解释为wchar_t (即unicode字符)。不幸的是,我相当肯定这是不可移植的,并且取决于ecl的配置方式和C++编译器。
// basic check that this should work
static_assert(sizeof(ecl_character)==sizeof(wchar_t),"sizes must be the same");
std::wcout << "A string: " << reinterpret_cast<wchar_t*>(y->string.self) << std::endl;
// prints hello, as required
// note the use of wcout另一种方法是使用lisp类型base-string,它确实使用char (lisp中的base-char)作为其字符类型。然后lisp代码读取
(defun return-a-base-string ()
(coerce "Hello" 'base-string))(可能有更优雅的方法来进行到base-string的转换,但我不知道它们)。
在C++中打印
cl_object y2 = lisp("(return-a-base-string)");
std::cout << "Another: " << y2->base_string.self << std::endl;(请注意,您不能在同一个程序中混合wcout和cout )
发布于 2016-03-15 20:53:40
发布于 2016-03-18 08:55:04
std::string str {""};
cl_object y2 = lisp("(return-a-base-string)");
//get dimension
int j = y2->string.dim;
//get pointer
ecl_character* selv = y2->string.self;
//do simple pointer addition
for(int i=0;i<j;i++){
str += (*(selv+i));
}
//do whatever you want to str此代码在从ecl_characters生成字符串时工作。
从文件中:
"ECL定义了两个C类型来保存它的字符: ecl_base_char和ecl_character。
在没有Unicode的情况下构建ECL时,它们都是重合的,并且通常匹配无符号字符,以覆盖所需的256段代码。当使用Unicode构建ECL时,这两种类型不再等价,ecl_character更大。要使代码具有可移植性和未来的证据,请使用这两种类型来真正表达您想要做的事情。“
https://stackoverflow.com/questions/36019502
复制相似问题