战魂小筑

讨论群:309800774 知乎关注:http://zhihu.com/people/sunicdavy 开源项目:https://github.com/davyxu

   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  257 随笔 :: 0 文章 :: 506 评论 :: 0 Trackbacks

#

CodeLite极力的模仿Visual Studio的界面及表现形式. 但是在有些配置项上却存在着操作不同, 看图说话:

image

这是项目中的工程配置设定项中的调试器参数设置. 图中将Program启动程序项设定为相对路径, 而Working Folder工作目录项设为绝对路径.

这样的设定无法启动调试器, gdb将报错, 无法找到调试程序:

image

研究了一下, 发现设定项里引导你使用浏览目录对话框进行选择, 尝试一下, 将Program改为绝对路径

image

F5开始调试, 不报错, main中使用getcwd获取当前路径验证, 设置正确, 问题解决

 

分析: CodeLite应该只是将两个参数简单的传给了gdb, 但是gdb并不知道工程相对路径,因此报错. 这对于CodeLite开发者来说,理解是正确的, 程序员思想.

但是对于产品来说是失败的

VisualStudio的调试器与IDE结合紧密, 因此以产品思想开发程序, 就能避免这种类似的问题

posted @ 2012-03-30 16:07 战魂小筑 阅读(5056) | 评论 (0)编辑 收藏

在lua中, #操作符用于获取对象大小, 对于table来说, 获取的是table元素个数, 对于字符串来说获取的是字符串长度

另外一种获取方法是table.getn(obj), 但是这个方法已经标记为废除了, 尽量使用通用且简洁的#操作符

 

使用lua api实现此功能就需要用到lua_objlen( ),但是这个功能未在luabind中提供.所以我们顺手添加一个

首先找到luabind源码的object.hpp中取对象类型的type函数,在其下添加以下代码

 

  1: template<class ValueWrapper>
  2: inline int obj_size(ValueWrapper const& value)
  3: {
  4:     lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(
  5:         value
  6:         );
  7: 
  8:     value_wrapper_traits<ValueWrapper>::unwrap(interpreter, value);
  9:     detail::stack_pop pop(interpreter, 1);
 10:     return lua_objlen(interpreter, -1);
 11: }

 

重新编译你的代码, 就可以这样使用luabind::obj_size( obj ) 获取对象大小了
posted @ 2012-03-27 17:36 战魂小筑 阅读(1839) | 评论 (0)编辑 收藏

以下代码使用luabind进行lua的coroutine测试

   1: void ScriptManagedChannel::OnServiceInitialize()
   2: {    
   3:     try
   4:     {        
   5:         mThread = lua_newthread( GScriptScriptContext->GetVM() );
   6:  
   7:         luabind::resume_function<void>( mThread, "ScriptMain", this );
   8:  
   9:         Resume();
  10:     }
  11:     catch (std::exception& e)
  12:     {
  13:         const char* ErrorMsg = lua_tostring( GScriptScriptContext->GetVM(), -1 );            
  14:         printf("%s\n", e.what() );
  15:     }
  16:  
  17:     
  18: }
  19:  
  20: void ScriptManagedChannel::Resume( )
  21: {
  22:     luabind::resume<void>( mThread );
  23: }
  24:  
  25: void ScriptManagedChannel::StopTest( )
  26: {
  27:     lua_yield( mThread, 0 );
  28: }
  29:  
  30:  

代码中, mThread类型为lua_State*类型

GScriptScriptContext->GetVM()是加载了代码的lua_State*

StopTest为注册为ScriptManagedChannel类成员函数到lua中的定义

接下来看lua端的测试代码:

   1: function ScriptMain( Channel )
   2:  
   3:     
   4:     for i = 1, 5 do
   5:     
   6:     print("done", i)
   7:     
   8:     Channel:StopTest( )
   9:     
  10:     
  11:     
  12:     end
  13: end

刚开始,在测试代码时, lua中有个手误而造成的错误, 导致C++代码运行到第7行时弹出assert

位于:luabind-0.9.1\luabind\detail\call_function.hpp 第264行,对应以下代码第13行

   1: ~proxy_function_void_caller()
   2: {
   3:     if (m_called) return;
   4:  
   5:     m_called = true;
   6:     lua_State* L = m_state;
   7:  
   8:     int top = lua_gettop(L);
   9:  
  10:     push_args_from_tuple<1>::apply(L, m_args);
  11:     if (m_fun(L, boost::tuples::length<Tuple>::value, 0))
  12:     {
  13:         assert(lua_gettop(L) == top - m_params + 1);
  14:  
  15: NO_EXCEPTIONS
  16:         throw luabind::error(L);
  17: #else
  18:         error_callback_fun e = get_error_callback();
  19:         if (e) e(L);
  20:     
  21:         assert(0 && "the lua function threw an error and exceptions are disabled."
  22:                 " If you want to handle the error you can use luabind::set_error_callback()");
  23:         std::terminate();
  24: #endif
  25:     }
  26:     // pops the return values from the function call
  27:     stack_pop pop(L, lua_gettop(L) - top + m_params);
  28: }

11行代码中调用的是lua_resume, 返回的是运行错误, 但是被13行的assert挡住了, 无法通过第16行抛出异常被外面捕获.

因此,尝试注释第13行, 再测试, 可以在lua抛出错误后, 在栈顶捕获到coroutine函数resume时报出的错误信息.问题解决

 

对于lua的coroutine, 网上资料不多, 这里有一篇比较详细的代码

我比较疑惑的是, 有没有必要将代码在dofile或者dobuffer时, 必须传入newthread出的state? 如果还是传入原始的state会有什么影响?

欢迎各位有此经验的讨论

posted @ 2012-03-27 10:38 战魂小筑 阅读(1498) | 评论 (2)编辑 收藏

我们有时需要限制lua代码的运行环境,或者是让使用者不能访问到lua的一些全局函数.lua语言本身没有类似于C++, C#, Java那样的成员访问控制. 但lua提供了setfenv函数可以很灵活的处理各类权限问题

废话不多说, 看代码

   1:  -- 创建沙盒
   2:  function SpawnSandBox( )
   3:   
   4:      local SandBoxGlobals = {}
   5:      
   6:      -- 基础函数添加
   7:      SandBoxGlobals.print             = print
   8:      SandBoxGlobals.table             = table
   9:      SandBoxGlobals.string             = string     
  10:      SandBoxGlobals.math               = math 
  11:      SandBoxGlobals.assert             = assert 
  12:      SandBoxGlobals.getmetatable    = getmetatable 
  13:      SandBoxGlobals.ipairs             = ipairs 
  14:      SandBoxGlobals.pairs             = pairs 
  15:      SandBoxGlobals.pcall             = pcall 
  16:      SandBoxGlobals.setmetatable    = setmetatable 
  17:      SandBoxGlobals.tostring        = tostring 
  18:      SandBoxGlobals.tonumber        = tonumber 
  19:      SandBoxGlobals.type            = type 
  20:      SandBoxGlobals.unpack             = unpack 
  21:      SandBoxGlobals.collectgarbage     = collectgarbage
  22:      SandBoxGlobals._G                = SandBoxGlobals
  23:      
  24:      return SandBoxGlobals
  25:  end
  26:   
  27:  -- 在沙盒内执行脚本, 出错时返回错误, nil表示正确
  28:  function ExecuteInSandBox( SandBox, Script )
  29:      
  30:      local ScriptFunc, CompileError = loadstring( Script )
  31:      
  32:      if CompileError then
  33:          return CompileError
  34:      end
  35:      
  36:      setfenv( ScriptFunc, SandBox )
  37:      
  38:      local Result, RuntimeError = pcall( ScriptFunc )
  39:      if RuntimeError then
  40:          return RuntimeError
  41:      end
  42:      
  43:      return nil
  44:  end
  45:   
  46:  function ProtectedFunction( )
  47:      print("protected func")
  48:  end
  49:   
  50:   
  51:  local SandBox = SpawnSandBox( )
  52:   
  53:   
  54:  print ( "Response=", ExecuteInSandBox( SandBox, "table.foreach( _G, print )" ) )
  55:   
  56:  print ( "Response=", ExecuteInSandBox( SandBox, "ProtectedFunction()" ) )
  57:   
  58:  SandBox.ProtectedFunction = ProtectedFunction
  59:   
  60:  print ( "Response=", ExecuteInSandBox( SandBox, "ProtectedFunction()" ) )

 

54行执行结果是

 

   1:  _G    table: 00421258
   2:  string    table: 00421050
   3:  pairs    function: 00567F58
   4:  collectgarbage    function: 005675F0
   5:  unpack    function: 004217E8
   6:  assert    function: 005675B0
   7:  print    function: 00567830
   8:  ipairs    function: 00567F28
   9:  type    function: 004217A8
  10:  tonumber    function: 00421768
  11:  tostring    function: 00421788
  12:  table    table: 00420DA8
  13:  math    table: 004210C8
  14:  setmetatable    function: 00421748
  15:  getmetatable    function: 00567710
  16:  pcall    function: 005677F0
  17:  Response=    nil
 
54行由于没有注册这个全局函数, 因此无法访问
Response=    [string "ProtectedFunction()"]:1: attempt to call global 'ProtectedFunction' (a nil value)
 
58行在全局环境中加上了这个函数,因此在60行访问正常
protected func
Response=    nil
 
posted @ 2012-03-02 09:40 战魂小筑 阅读(4080) | 评论 (0)编辑 收藏

Linux下的ldd命令可以查看一个可执行文件/共享库/静态库的依赖, 但是想得到这些依赖文件, 必须手动去找,非常麻烦

这里是一个Shell可以将依赖列表中的文件拷贝到指定目录

deplist=$( ldd $1 | awk '{if (match($3,"/")){ print $3}}' )
cp $deplist $2
代码解释: ldd导出列表, 这个列表打印出来很丑

linux-gate.so.1 =>  (0x00ed2000)
    liblog4cpp.so.4 => /usr/local/lib/liblog4cpp.so.4 (0x00657000)
    libprotobuf.so.7 => /usr/local/lib/libprotobuf.so.7 (0x00360000)
    libboost_filesystem.so.1.48.0 => /usr/local/lib/libboost_filesystem.so.1.48.0 (0x00a9a000)
    libboost_program_options.so.1.48.0 => /usr/local/lib/libboost_program_options.so.1.48.0 (0x00110000)
    libboost_system.so.1.48.0 => /usr/local/lib/libboost_system.so.1.48.0 (0x00a85000)
    libboost_thread.so.1.48.0 => /usr/local/lib/libboost_thread.so.1.48.0 (0x00179000)
    libunwind-x86.so.7 => /usr/lib/libunwind-x86.so.7 (0x00821000)
    libluabindd.so.0.9.0 => /usr/local/lib/libluabindd.so.0.9.0 (0x00bb3000)
    libmysqlpp.so.3 => /usr/local/lib/libmysqlpp.so.3 (0x00de5000)
    libstdc++.so.6 => /usr/lib/i386-linux-gnu/libstdc++.so.6 (0x001a9000)
    libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0x00782000)
    libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0x00aea000)
    libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00447000)
    libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0x00abd000)
    librt.so.1 => /lib/i386-linux-gnu/librt.so.1 (0x00193000)
    libnsl.so.1 => /lib/i386-linux-gnu/libnsl.so.1 (0x00294000)
    libunwind.so.7 => /usr/lib/libunwind.so.7 (0x002ab000)
    libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 (0x00e8a000)
    libmysqlclient_r.so.16 => /usr/lib/libmysqlclient_r.so.16 (0x0083b000)
    /lib/ld-linux.so.2 (0x00608000)
    libz.so.1 => /lib/i386-linux-gnu/libz.so.1 (0x002c0000)

 

我们发现第一行的so没有对应的库地址, 因此我们使用awk的脚本功能,判断第三个参数,也就是=>之后的路径必须包含/

之后将第一行的输出重定向到变量中, 再使用cp指令从列表拷贝到指定目录

posted @ 2012-02-29 16:05 战魂小筑 阅读(2974) | 评论 (0)编辑 收藏

1.1 为进程添加守护进程

参考链接http://yubosun.akcms.com/tech/linux-daemon-program.htm

   1:  #include <unistd.h> 
   2:  #include <signal.h> 
   3:  #include <sys/types.h> 
   4:  #include <sys/stat.h> 
   5:  #include <stdio.h> 
   6:  #include <stdlib.h>
   7:   
   8:  #ifndef NOFILE 
   9:  #define NOFILE 3 
  10:  #endif
  11:   
  12:  void init_daemon() 
  13:  { 
  14:          int pid; 
  15:          int i; 
  16:          if(pid = fork()) exit(0); //父进程,退出 
  17:   
  18:          else if(pid < 0) exit(1); //fork失败 
  19:   
  20:          /* 子进程继续执行 */ 
  21:          setsid(); //创建新的会话组,子进程成为组长,并与控制终端分离 
  22:   
  23:          /* 防止子进程(组长)获取控制终端 */ 
  24:          if(pid = fork()) exit(0); //父进程,退出 
  25:   
  26:          else if(pid < 0) exit(1); //fork错误,退出 
  27:   
  28:          /* 第二子进程继续执行 , 第二子进程不再是会会话组组长*/ 
  29:   
  30:          //for(i = 0; i < NOFILE; i++) /* 关闭打开的文件描述符*/ 
  31:          //{ 
  32:          //close(i); 
  33:          //} 
  34:          chdir("/tmp"); /* 切换工作目录 */ 
  35:          umask(0); /* 重设文件创建掩码 */ 
  36:          return; 
  37:  }
  38:   
  39:  int main(int argc, char* argv[])
  40:  {    
  41:      FILE *fp; 
  42:   
  43:      signal(SIGCHLD, SIG_IGN); /* 忽略子进程结束信号,防止出现僵尸进程 */ 
  44:   
  45:      init_daemon(); 
  46:   
  47:      while(1) 
  48:      { 
  49:              sleep(1);
  50:              
  51:  // 注意, 日志写到这个目录
  52:              if((fp = fopen("/var/tmp/test.log", "a")) != NULL) 
  53:              { 
  54:                      fprintf(fp, "%s\n", "test message"); 
  55:                      fclose(fp); 
  56:              } 
  57:      } 
  58:   
  59:      return 0;
  60:  }

1.2 编写服务脚本

参考链接http://blog.sina.com.cn/s/blog_57421ff80100c7nn.html

红色字是需要填写的部分, 文件头部分可以选填

   1:  #!/bin/bash
   2:   
   3:  # chkconfig: 3 3 1
   4:   
   5:  # description: web kill center
   6:   
   7:  EXEC_PATH=/usr/local/bin
   8:   
   9:  EXEC=CenterServiced
  10:   
  11:  PID_FILE=/var/run/CenterServiced.pid
  12:   
  13:  DAEMON=/usr/local/bin/CenterServiced
  14:   
  15:  if ! [ -x $EXEC_PATH/$EXEC ] ; then
  16:   
  17:  echo "ERROR: $EXEC_PATH/$EXEC not found"
  18:   
  19:  exit 1
  20:   
  21:  fi
  22:   
  23:  stop()
  24:   
  25:  {
  26:   
  27:  echo "Stoping $EXEC ..."
  28:   
  29:  killall $DAEMON >/dev/null
  30:   
  31:  echo "Shutting down $EXEC: [ OK ]"
  32:   
  33:  }
  34:   
  35:  start()
  36:   
  37:  {
  38:   
  39:  echo "Starting $EXEC ..."
  40:   
  41:  $DAEMON > /dev/null &
  42:   
  43:  echo "Starting $EXEC: [ OK ]"
  44:   
  45:  }
  46:   
  47:  restart()
  48:   
  49:  {
  50:   
  51:  stop
  52:   
  53:  start
  54:   
  55:  }
  56:   
  57:  case "$1" in
  58:   
  59:  start)
  60:   
  61:  start
  62:   
  63:  ;;
  64:   
  65:  stop)
  66:   
  67:  stop
  68:   
  69:  ;;
  70:   
  71:  restart)
  72:   
  73:  restart
  74:   
  75:  ;;
  76:   
  77:  status)
  78:   
  79:  status -p $PID_FILE $DAEMON
  80:   
  81:  ;;
  82:   
  83:  *)
  84:   
  85:  echo "Usage: service $EXEC {start|stop|restart|status}"
  86:   
  87:  exit 1
  88:   
  89:  esac
  90:   
  91:  exit $?
  92:   

1.3 创建服务

参考链接http://hi.baidu.com/guanxiansun/blog/item/b4c7dcf55f6011e47709d724.html

将服务文件拷贝到/etc/init.d下,去掉扩展名, 文件名即是服务名

chmod +x ./wkcenter

如果不设置启动, 那么service中将无法找到该服务及操作

1.4 设置启动顺序

创建启动链接

ln /etc/init.d/wkcenter /etc/rc3.d/S03wkcenter

创建关闭链接

ln /etc/init.d/wkcenter /etc/rc0.d/K03wkcenter

1.5 添加服务

chkconfig --add wkcenter

查看服务是否存在

chkconfig –-list | grep wkcenter

查看服务状态

chkconfig wkcenter on

注意, 确认wkcenter在2,3,4,5中任意或者部分开启, 必须为绿字. 灰字代表服务无法开机启动或者其他问题

1.6 测试

临时开启命令测试

service wkcenter start

1.7 QA

参考链接: http://blog.526net.com/?p=1706

1. 服务切记不可放在用户home目录, 最好放在/usr/local/bin目录, 日志写到var中, 否则服务测试正常,但是无法自动启动

2. Linux下, 父进程启动的程序的生命期跟随父进程, 父进程可以是终端, 父进程一旦终止, 子进程都必须结束. 因此守护进程需要脱离父进程,避免被父进程生命期控制

posted @ 2012-02-28 10:52 战魂小筑 阅读(7265) | 评论 (4)编辑 收藏

参考来源:http://blog.csdn.net/flying8127/article/details/1598521

在原来原基础上,将代码整理,并加强安全性. 并按照WindowsAPI设计, 添加输出缓冲长度探测功能

当OutUTFString为NULL时, 可以进行输出的UTF8字符串长度探测

   1:  uint32 UniCharToUTF8(wchar_t UniChar, char *OutUTFString)
   2:      {
   3:   
   4:          uint32 UTF8CharLength = 0;
   5:   
   6:          if (UniChar < 0x80)
   7:          {  
   8:              if ( OutUTFString )
   9:                  OutUTFString[UTF8CharLength++] = (char)UniChar;
  10:              else
  11:                  UTF8CharLength++;
  12:          }
  13:          else if(UniChar < 0x800)
  14:          {
  15:              if ( OutUTFString )
  16:              {
  17:                  OutUTFString[UTF8CharLength++] = 0xc0 | ( UniChar >> 6 );
  18:                  OutUTFString[UTF8CharLength++] = 0x80 | ( UniChar & 0x3f );
  19:              }
  20:              else
  21:              {
  22:                  UTF8CharLength += 2;
  23:              }
  24:          }
  25:          else if(UniChar < 0x10000 )
  26:          {
  27:              if ( OutUTFString )
  28:              {
  29:                  OutUTFString[UTF8CharLength++] = 0xe0 | ( UniChar >> 12 );
  30:                  OutUTFString[UTF8CharLength++] = 0x80 | ( (UniChar >> 6) & 0x3f );
  31:                  OutUTFString[UTF8CharLength++] = 0x80 | ( UniChar & 0x3f );
  32:              }
  33:              else
  34:              {
  35:                  UTF8CharLength += 3;
  36:              }
  37:          }
  38:          else if( UniChar < 0x200000 ) 
  39:          {
  40:              if ( OutUTFString )
  41:              {
  42:                  OutUTFString[UTF8CharLength++] = 0xf0 | ( (int)UniChar >> 18 );
  43:                  OutUTFString[UTF8CharLength++] = 0x80 | ( (UniChar >> 12) & 0x3f );
  44:                  OutUTFString[UTF8CharLength++] = 0x80 | ( (UniChar >> 6) & 0x3f );
  45:                  OutUTFString[UTF8CharLength++] = 0x80 | ( UniChar & 0x3f );
  46:              }
  47:              else
  48:              {
  49:                  UTF8CharLength += 4;
  50:              }
  51:   
  52:          }
  53:   
  54:          return UTF8CharLength;
  55:      }

 

当OutUnicodeString为NULL时, 可以进行输出的Unicode字符串长度探测

 

   1:  uint32 UTF8StrToUnicode( const char* UTF8String, uint32 UTF8StringLength, wchar_t* OutUnicodeString, uint32 UnicodeStringBufferSize )
   2:      {
   3:          uint32 UTF8Index = 0;
   4:          uint32 UniIndex = 0;
   5:   
   6:          while ( UTF8Index < UTF8StringLength )
   7:          {
   8:              unsigned char UTF8Char = UTF8String[UTF8Index];
   9:   
  10:              if ( UnicodeStringBufferSize != 0 && UniIndex >= UnicodeStringBufferSize )
  11:                  break;
  12:   
  13:              if ((UTF8Char & 0x80) == 0) 
  14:              {
  15:                  const uint32 cUTF8CharRequire = 1;
  16:   
  17:                  // UTF8字码不足
  18:                  if ( UTF8Index + cUTF8CharRequire > UTF8StringLength )
  19:                      break;
  20:   
  21:                  if ( OutUnicodeString )
  22:                  {
  23:                      wchar_t& WideChar = OutUnicodeString[UniIndex]; 
  24:   
  25:                      WideChar = UTF8Char;
  26:                  }
  27:   
  28:                  UTF8Index++;
  29:                  
  30:              } 
  31:              else if((UTF8Char & 0xE0) == 0xC0)  ///< 110x-xxxx 10xx-xxxx
  32:              {
  33:                  const uint32 cUTF8CharRequire = 2;
  34:   
  35:                  // UTF8字码不足
  36:                  if ( UTF8Index + cUTF8CharRequire > UTF8StringLength )
  37:                      break;
  38:   
  39:                  if ( OutUnicodeString )
  40:                  {
  41:                      wchar_t& WideChar = OutUnicodeString[UniIndex]; 
  42:                      WideChar  = (UTF8String[UTF8Index + 0] & 0x3F) << 6;
  43:                      WideChar |= (UTF8String[UTF8Index + 1] & 0x3F);
  44:                  }
  45:                  
  46:                  UTF8Index += cUTF8CharRequire;
  47:              }
  48:              else if((UTF8Char & 0xF0) == 0xE0)  ///< 1110-xxxx 10xx-xxxx 10xx-xxxx
  49:              {
  50:                  const uint32 cUTF8CharRequire = 3;
  51:   
  52:                  // UTF8字码不足
  53:                  if ( UTF8Index + cUTF8CharRequire > UTF8StringLength )
  54:                      break;
  55:   
  56:                  if ( OutUnicodeString )
  57:                  {
  58:                      wchar_t& WideChar = OutUnicodeString[UniIndex]; 
  59:   
  60:                      WideChar  = (UTF8String[UTF8Index + 0] & 0x1F) << 12;
  61:                      WideChar |= (UTF8String[UTF8Index + 1] & 0x3F) << 6;
  62:                      WideChar |= (UTF8String[UTF8Index + 2] & 0x3F);
  63:                  }
  64:                  
  65:   
  66:                  UTF8Index += cUTF8CharRequire;
  67:              } 
  68:              else if((UTF8Char & 0xF8) == 0xF0)  ///< 1111-0xxx 10xx-xxxx 10xx-xxxx 10xx-xxxx 
  69:              {
  70:                  const uint32 cUTF8CharRequire = 4;
  71:   
  72:                  // UTF8字码不足
  73:                  if ( UTF8Index + cUTF8CharRequire > UTF8StringLength )
  74:                      break;
  75:   
  76:                  if ( OutUnicodeString )
  77:                  {
  78:                      wchar_t& WideChar = OutUnicodeString[UniIndex]; 
  79:   
  80:                      WideChar  = (UTF8String[UTF8Index + 0] & 0x0F) << 18;
  81:                      WideChar  = (UTF8String[UTF8Index + 1] & 0x3F) << 12;
  82:                      WideChar |= (UTF8String[UTF8Index + 2] & 0x3F) << 6;
  83:                      WideChar |= (UTF8String[UTF8Index + 3] & 0x3F);
  84:                  }
  85:   
  86:                  UTF8Index += cUTF8CharRequire;
  87:              } 
  88:              else ///< 1111-10xx 10xx-xxxx 10xx-xxxx 10xx-xxxx 10xx-xxxx 
  89:              {
  90:                  const uint32 cUTF8CharRequire = 5;
  91:   
  92:                  // UTF8字码不足
  93:                  if ( UTF8Index + cUTF8CharRequire > UTF8StringLength )
  94:                      break;
  95:   
  96:                  if ( OutUnicodeString )
  97:                  {
  98:                      wchar_t& WideChar = OutUnicodeString[UniIndex]; 
  99:   
 100:                      WideChar  = (UTF8String[UTF8Index + 0] & 0x07) << 24;
 101:                      WideChar  = (UTF8String[UTF8Index + 1] & 0x3F) << 18;
 102:                      WideChar  = (UTF8String[UTF8Index + 2] & 0x3F) << 12;
 103:                      WideChar |= (UTF8String[UTF8Index + 3] & 0x3F) << 6;
 104:                      WideChar |= (UTF8String[UTF8Index + 4] & 0x3F);
 105:                  }
 106:   
 107:                  UTF8Index += cUTF8CharRequire;
 108:              }
 109:   
 110:   
 111:              UniIndex++;
 112:          }
 113:   
 114:          return UniIndex;
 115:      }

疗效: 用了此代码啊, 再也不用被iconv折磨了

posted @ 2012-02-27 14:21 战魂小筑 阅读(4653) | 评论 (9)编辑 收藏

hash_map不是标准库,因此不同平台下包含头文件不同, 前缀也不同,这里使用了一个通用定义

   1:  #ifdef _WIN32
   2:      #include <hash_map>
   3:      #define HASHMAP_PREFIX stdext
   4:  #else
   5:      #include <ext/hash_map>
   6:      #define HASHMAP_PREFIX __gnu_cxx    
   7:  #endif

对于初始桶大小设置,Linux下使用hash_map构造函数可以设置, Windows下则没有对应的设置函数.

查阅Windows下hash_map的源码,并在hash_map()默认构造函数旁边添加一个测试用初始桶设置函数

   1:      hash_map( size_type _Buckets )
   2:          : _Mybase(key_compare(), allocator_type())
   3:      {
   4:          _Init( _Buckets );
   5:      }

接下来使用相同的测试代码

   1:      const uint32 Buckets = 1000;
   2:      HASHMAP_PREFIX::hash_map<uint32,uint32> MyHash( Buckets );
   3:   
   4:      TimeRuler Ruler;
   5:      for ( uint32 i = 0; i <1000000;i++)
   6:      {
   7:          MyHash[i] = i;
   8:      }
   9:   
  10:      printf("%d\n", Ruler.GetCostTime() );

这里的TimeRuler是使用boost timer的时间戳封装

Release下测试结果:

    OS \ Buckets           8 ( default )         1000
     Win7          430ms       560ms
     Mint( VMware )          127ms       127ms

 

Windows的测试结果说明, 不给出桶初始化函数是正确的, 默认管理比自己设置更高效.

Linux平台感觉很诡异, 不清楚是不是虚拟机造成的结果不准确

posted @ 2012-02-23 18:54 战魂小筑 阅读(1558) | 评论 (0)编辑 收藏

之前看了网上一篇文章介绍luabind, 发现这种编译出来的luabind只会安装debug版本, release版本的so依然坦然的躺在工程目录

查阅bjam的参数说明及luabind的jamroot文件第240行有如下文字

install stage
  : luabind
  : <location>$(stage-locate)
    <install-no-version-symlinks>on
    <install-dependencies>on
    <install-type>LIB
  ;

说明参数应该是这样的: bjam install [stage]

而且文章中给出的是bjam install 因此默认出调试版也是正确的, 而且估计作者只编译了调试版就没有处理release版了

正确的luabind编译法应该是:

export BOOST_ROOT=/home/davy/dev/boost_1_48_0

export LUA_PATH=/usr/local/

/home/davy/dev/boost_1_48_0/bjam stage --toolset=gcc --with-date_time --with-fpic --with-filesystem link=static debug release

/home/davy/dev/boost_1_48_0/bjam install debug

/home/davy/dev/boost_1_48_0/bjam install release

 

我这里必须指明bjam是因为boost的bjam版本高于默认安装的版本, 因此使用高版本编译

posted @ 2012-02-21 11:23 战魂小筑 阅读(2602) | 评论 (1)编辑 收藏

默认的, VC调试器只能正常显示ANSI字符串及UNICODE字符串, 而UTF-8字符串及其他格式则无法显示

这里无需编写插件及修改配置文件,只需要将要显示的字符串拉到Watch中,并在变量后面添加,s8即可显示

image --> image

同样类型的功能也应该很熟悉

,数字  将变量拆分为数组显示, 数字是要显示多少位, 此法对const char*这类原始字符串非常有用

,x 16进制查看

,hr  查看Windows HRESULT解释

,wm Windows消息,例如0x0010, wm 显示 WM_CLOSE

posted @ 2012-02-14 15:21 战魂小筑 阅读(7003) | 评论 (3)编辑 收藏

仅列出标题
共26页: First 6 7 8 9 10 11 12 13 14 Last