【问题标题】:std::cout, ostream and other kinds of getting output streamstd::cout, ostream 和其他类型的获取输出流
【发布时间】:2017-01-18 23:37:02
【问题描述】:

在我的项目(虚幻引擎 4)中,我没有输出流 - 取而代之的是,我可以通过 UE_LOG 函数进行通信,该函数的工作方式与 printf() 非常相似。问题是我刚刚创建了一个 .dll 库(没有 Unreal 包含),我想通过 iostream 进行通信。我的想法是 - 在 .dll 库中,我使用标准的 cout 将消息写入 ostream,我在虚幻引擎函数中使用所有这些,我以字符串的形式获取 ostream 并将其输出到 UE_LOG 函数中。

问题是我一直将std::cout 视为魔法的一部分,而没有考虑里面到底是什么(我很确定我们大多数人都这样做了)。我该如何处理?简单的方法行不通(比如抓取stringstream 并将其输出到UE_LOG)。

【问题讨论】:

  • 包装这些东西以匹配std::ostream 语法。大笑:D
  • 既然可以传递字符串,为什么还要传递流?让 DLL 中的函数接受 std::string 参数,如果它们需要返回字符串,则返回 std::string
  • @joachim-pileborg 是的,但是 dll 函数会产生复杂的过程,并且必须在执行前后调用 - 所以仅仅抓住字符串是没有帮助的。
  • 我不确定我是否完全理解您想要什么,但您检查过stringstream吗?
  • @Revolver_Ocelot 哟,最后一行是关于这个的。或者我不知道一些隐藏的功能,比如实时更新或smth。

标签: c++ std iostream


【解决方案1】:

我的想法是 - 在 .dll 库中,我使用标准 cout 将消息写入 ostream

您实际上可以用您自己的实现替换std::cout 使用的输出缓冲区。使用std::ostream::rdbuf() 函数来执行此操作(参考文档中的示例):

#include <iostream>
#include <sstream>

int main()
{
    std::ostringstream local;
    auto cout_buff = std::cout.rdbuf(); // save pointer to std::cout buffer

    std::cout.rdbuf(local.rdbuf()); // substitute internal std::cout buffer with
        // buffer of 'local' object

    // now std::cout work with 'local' buffer
    // you don't see this message
    std::cout << "some message";

    // go back to old buffer
    std::cout.rdbuf(cout_buff);

    // you will see this message
    std::cout << "back to default buffer\n";

    // print 'local' content
    std::cout << "local content: " << local.str() << "\n";
}

【讨论】:

  • 我不知道如何制作local.rdbuf。请记住,我有 printf 形式的功能。只有 c_strings、整数等我可以传递。
  • 想法非常好,但我只需要重载 std::ostringstream::flush 函数(或其他负责在终端上刷新内容的函数)以自动将内容写入我的输出控制台(你知道,UE_LOG 与 printf 类似)。
  • @CheshireCat “我需要做的一件事是重载 std::ostringstream::flush 函数” 如果您从自己的实现中重载,我认为 std::basic_streambuf::sync() 将负责这样做。
  • 好吧,总比没有好,但它仍然没有给我提供实时更新的方法。我会寻找类似的东西,也许是从类继承的。仍然 +1 给我提示 rdbuf :)
【解决方案2】:

(以防我的编辑不会得到正面评价)

来自 OP:感谢您的提示,我终于找到了解决问题的方法。假设我想从 cout 获取流并将其发送到 printf(因为我认为 stdio 库优于 iostream)。我该怎么做:

#include <iostream>
#include <sstream>
#include <cstdio>

using namespace std;

class ssbuf : public stringbuf{
protected:
    int sync(){
        printf("My buffer: %s",this->str().c_str());
        str("");
        return this->stringbuf::sync();
    }
};


int main(){
    ssbuf *buf = new ssbuf();
    cout.rdbuf(buf);
    cout<<"This is out stream "<<"and you cant do anything about it"<<endl;
    cout<<"(don't) "<<"Vote Trump"<<endl;
}

代码非常原始,但它可以完成它的工作。我制作了具有方法sync()向下转换原始虚拟方法sync()的缓冲区子类。除此之外,它像通常的缓冲区一样工作,只是抓取所有控制台输出流——正是我们想要的。里面的 str("") 是清理缓冲区——可能没有输出的流不会自己清理。

非常感谢您的帮助!大笑给你! :D

【讨论】:

    猜你喜欢
    • 2010-09-26
    • 2019-10-24
    • 1970-01-01
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    • 2014-05-10
    • 2019-03-05
    • 2013-07-28
    相关资源
    最近更新 更多