星期六, 四月 19, 2008

在 C++ 当中调用 Python 时异常信息的获取

    使用Boost::Ptyhon 可以很方便的将C++当中的对象暴露给 Python 对象,同时也可以通过 虚函数 而后在 Python 当中重写的方式来实现运行时的多态。但是如何在 C++ 当中获取 Python 运行时的错误呢?翻遍了Boost::Python的文档我都没有找到,只是在 Python 的 C API 当中发现了这个方法:


void PyErr_Print( )

Print a standard traceback to sys.stderr and clear the error indicator. Call this function only when the error indicator is set. (Otherwise it will cause a fatal error!)

想当然的就认为和在 C 里面一样,有了 perror 一样,就应该有 strerror 。于是我找啊找啊,就是找不到。没办法了,G了一把之后曲线救国。先在 Python 里面重定向 stderr,然后通过 PyErr_Print 获取异常信息,然后自己再取出来,具体实现如下:

class ErrorCatcher

{//助手类,用来获取python脚本的错误文本

public:

   ErrorCatcher() { clear(); }

   void write( const std::string& str ) { m_text.append(str); }

 

   const std::string& what(void) { return m_text; }

   void clear(void) { m_text.clear(); }

 

private:

   std::string m_text;

};

当然,还是要把这个类导出到 Python 当中:

namespace bp = boost::python;

bp::class_<Base::ErrorCatcher,Base::ErrorCatcherPtr, boost::noncopyable >("ErrorCatcher")

.def( "write", &Base::ErrorCatcher::write )

;

在 Python 脚本的头上这么写:

    #为了配合C++获取异常的错误信息
    import sys
    oldstdcerr = sys.stderr ;
    newstdcerr = core.initalize(...);
    sys.stderr = newstdcerr ;
    #异常处理设置完毕

之后在 C++ 当中调用脚本的时候,可以通过这样的方式来捕获异常:

void processPyException()

{

   const char* desc = NULL;

   if( PyErr_ExceptionMatches(PyExc_ZeroDivisionError) ) {

      desc = "除异常!";

   } // process others errors

 

   PyErr_Print();

   logger.write(desc,gErrorCatcher->what() );

   gErrorCatcher->clear();

}

try{

   ...;//调用脚本

}catch (boost::python::error_already_set& ){

   processPyException();

}

 

在脚本当中发生的异常的输出类似于:

2008-04-19 17:34:23 (2628) [Application] ERROR 执行脚本时发生异常:Traceback (most recent call last):
  File "C:\codes\work\XXXX\debug\StdAlgorithms\XXXXX.py", line 23, in compute
    sonRelationList = mp.getSonRelations();
Boost.Python.ArgumentError: Python argument types in
    MeterPoint.getSonRelations(MeterPoint)
did not match C++ signature:
    getSonRelations(class Core::MeterPoint {lvalue}, class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > relaString)


实在是难以理解为啥 Python 不提供一个直接获取错误字符串描述或者根据错误码获取错误信息的 API。

若有更好的方法,敬请各位看官指教。

#EOF


 

 

星期日, 四月 06, 2008

开始更新BLOG

不知道因为什么原因(奥运会?),GFW 突然开放了 blogspot 的浏览。所以我决定开始持续更新本BLOG,作为我生活、工作的记录。

星期六, 四月 05, 2008

Windows平台编译安装 OpenSSL 0.9.8g



Windows平台编译安装 OpenSSL 0.9.8g

http://xuziding.blogspot.com/2008/04/windows-openssl-098g.html

  1. 需要
    • MS VC 80(其他6.0版本以及以上的都可以)
    • Perl (可以使用AvtivePrel)
    • openssl-0.9.8g.zip (可从 www.openssl.org 下载)
  2. 准备
    • 将 openssl-0.9.8g.zip 解压缩到目录 E:\libs\openssl-0.9.8g 下
    • 打开VC命令行编译环境。start ->Microsoft Visual Studio 2005->Visual Studio Tools->Visual Studio 2005 Command Prompt
    • 将 perl.exe 加入PATH 当中。set PATH=C:\Activeprel\bin;%path%
  3. 配置
    • > cd E:\libs\openssl-0.9.8g
    • > perl Configure enable-camellia threads zlib no-shared enable-camellia --openssldir=D:/Dev/libs/openssl-0.9.8g -IE:/libs/zlib-1.2.3 -LE:/libs/zlib-1.2.3/lib/zlib.lib VC-WIN32
      ('enable-camellia' 打开对称密码 'Camellia' (128-bit, 192-bit, 256-bit key 版本))
      (--openssldir=要安装到哪里的目录其中注意路径要用 Unix 路径分隔符 / 来分隔)
  4. 编译
    • 编译汇编的优化代码 > ms\do_masm 执行完了这一步,所有的 makefile 都已经生成好了,若你需要自定义一些与默认的编译选项不一致的东西,就需要手工更改。比如你的 zlib.lib 的 PATH ,使用的 CRT 的版本是(MD还是MDd)等等。
    • 编译库 > nmake -f ms\nt.mak (nt.mak 为静态lib,ntdll.mak 为 DLL 版本)
  5. 测试、安装
    • 测试库 > nmake -f ms\nt.mak test 若测试通过,最后应该告诉你 all test passed.
    • 安装库 > nmake -f ms\nt.mak install 安装库和头文件到上面指定的要安装目录
  6. 测试安装好的程序
    • 执行 openssl
    • OpenSSL> version (应该输出 OpenSSL 0.9.8g 19 Oct 2007 )
    • OpenSSL> s_client -connect www.openssl.org:443 (回车)
    • GET /(两次回车) 这时候应该显示出来www.openssl.org 的首页的 html 代码。