1

我有一个可执行文件(fossil scm),我的程序通过 ::CreateProcess windows 调用在外部调用它。然后捕获标准输出和标准错误。由于化石的源代码可用,我更愿意从中创建一个静态库并直接发出调用。目前,与fossil的通信是通过命令行参数完成的,返回的通信是通过进程返回码、stdout和stderr。Fossil 通过 printf 和 fprintf 调用写入 stdout/err。

以最少的化石来源改变来解决这个问题的最佳方法是什么?是否有可靠且跨平台的方法来拦截 stdout/err 并将其发送到内存缓冲区?

4

3 回答 3

3

你说你想

拦截 stdout/err 并将其发送到内存缓冲区

这表明您不想为 SCM 程序引入 API,而是希望在不更改现有代码的情况下继续解析文本输出。如果是这样,那么我认为改变您当前的方法没有任何意义。通过在当前方法上使用内存缓冲区和静态链接究竟可以获得什么?

于 2010-12-25T18:44:12.220 回答
3

您可以按照以下步骤进行操作:

  • 将化石的主要功能重命名为其他名称,以便您可以调用它
  • 在调用化石的 main 之前,将 stdout/stderr 重定向到您选择的文件:

freopen("filename.out", "w", stdout);

  • 形成一个参数数组,调用fossil_main,从文件中读取输出。
  • 您需要恢复标准输出流状态;没有跨平台机制,但您可以使用一些伪句柄(即 Windows 上的 CONOUT$)。

但是,请注意这是脆弱的:

  • 可能有一些全局变量应该在 main() 的开头被初始化为零,这对于第二次调用 main() 来说是不正确的
  • 化石可能会更改某些进程/线程状态(语言环境、当前目录等),您将无法可靠地恢复它。一个特别糟糕的情况是调用 exit(n)。
  • 进程终止时不会进行通常的清理 - 期望文件句柄保持打开状态(这样您将无法再次打开它们,如果它们在没有共享的情况下打开),内存泄漏等。
  • 显然,现在化石中的崩溃/挂起将更难处理(您有时可以解决这个问题)

通常,您可以这样做,但除非您有充分的理由(即性能)并且您准备好面对后果并自己修复错误,否则不要这样做。

于 2010-12-25T18:48:52.397 回答
0

将化石变成一个共享库,然后从您的自定义程序中使用它。

于 2010-12-25T18:35:00.970 回答