使用 ctypes 捕获 c++ 共享库日志条目
Capture c++ shared library log entries with ctypes
我有一个cplusplus共享库,带有c接口,可以在stdout中写入日志条目。我正在使用ctypes
库在 python 应用程序中使用它。python 应用程序使用logging
库来写入日志条目。
我需要做的是捕获共享库的 stdout 条目,以使用 logging
模块写入日志条目。换句话说,我想将 c 库的 stdout 条目重定向到 logging
模块,这样我就可以使用 logging
通过其处理程序写入文件和控制台。
我发现可以捕获标准输出(请参阅此 SO 问题(,但我只能在 c 模块调用结束时访问它,因此它对日志记录毫无用处。我想要一种非阻塞的方式来访问标准输出条目。
一个最小示例如下。
模块.cpp(使用 g++ -fPIC -shared module.cpp -o module.so
编译(
#include <unistd.h>
#include <iostream>
using namespace std;
extern "C" int callme()
{
cout<<"Hello worldn";
sleep(2);
cout<<"Some wordsn";
sleep(2);
cout<<"Goodby worldn";
return 0;
}
调用它的 python 应用程序:
import ctypes as ct
import logging
format='%(asctime)s - %(levelname)s - %(message)s', level=logging.DEBUG
logging.basicConfig(format=format)
logging.debug('This logging modules works like a charm!')
mymodule = ct.CDLL('./module.so')
mymodule.callme()
logging.info('I want to capture the shared library log entries')
logging.warning('Can I?')
这会产生:
2016-02-04 16:16:35,976 - DEBUG - This logging modules works like a charm!
Hello world
Some words
Goodby world
2016-02-04 16:16:39,979 - INFO - I want to capture the shared library log entries
2016-02-04 16:16:39,979 - WARNING - Can I?
我可以访问 c++ 库,因此也欢迎需要在库中修改的解决方案。
您应该能够在 C 模块调用运行时通过线程中的管道读取来修改链接答案中的代码。以下内容应该有效,尽管我还没有使用长时间运行的模块调用对其进行测试:
def redirected_printed_output(module_call):
# the pipe would fail for some reason if I didn't write to stdout at some point
# so I write a space, then backspace (will show as empty in a normal terminal)
sys.stdout.write(' b')
pipe_out, pipe_in = os.pipe()
# save a copy of stdout
stdout = os.dup(1)
# replace stdout with our write pipe
os.dup2(pipe_in, 1)
# check if we have more to read from the pipe
def more_data():
r, _, _ = select.select([pipe_out], [], [], 0)
return bool(r)
# read the pipe, writing to (former) stdout
def write_pipe_to_stdout():
while more_data():
os.write(stdout, os.read(pipe_out, 1024))
done = False
def read_loop():
# rewrite the pipe out to stdout in a loop while the call is running
while not done:
write_pipe_to_stdout()
# Finish the remnants
write_pipe_to_stdout()
t = threading.Thread(target=read_loop)
t.start()
module_call()
done = True
t.join() # wait for the thread to finish
# put stdout back in place
os.dup2(stdout, 1)
我按如下方式对其进行了测试(OSX(:
import ctypes
libc = ctypes.CDLL('libc.dylib')
def zomg():
for i in xrange(5):
libc.printf('libc stdout: %dn', i)
time.sleep(1)
redirected_printed_output(zomg)
相关文章:
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 在cuda线程之间共享大量常量数据
- 如何从具有移动语义的类对象中生成共享指针
- 在c代码之间共享数据的最佳方式
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- EvtExportLogneneneba API正在将远程计算机的事件日志保存到远程PC本身.如何将其保存到主机
- 将静态库链接到不带-fPIC的共享库中
- 为什么std::互斥需要很长的、非常不规则的时间来共享
- 使用Boost Interprocess创建托管共享内存需要很长时间
- 无法在Ubuntu上将共享库与Eclipse链接
- 从python调用openMP共享库时,未定义opnMP函数
- 在为LINUX创建共享库时,如何避免STL的私有/弱副本
- 为什么我的共享库中存在展开符号
- 使用共享指针的函数调用,其对象应为 const
- 具有两个独占锁组的共享锁
- gdb:如何将共享库的日志文件重定向到 gdb 输出
- Boost日志在链接到共享库时无法正常工作
- 使用 ctypes 捕获 c++ 共享库日志条目
- 共享库中的Boost日志通道过滤在linux上没有按预期工作