??xml version="1.0" encoding="utf-8" standalone="yes"?>
开发效率:(x)Windows下可以通过VisualStudioq行开发,其他q_可以使用MonoDevelopQ非常方?/p>
q行效率QJIT的性能优化比较CQ能适应90%性能环境
部v便捷性:(x)可以通过交叉~译生成其他q_的可执行文gQ通过monoq行可执行文?/p>
调试便捷性:(x)VisualStudio和MonoDevelop调试均很方便Q?q可q程调试
上手度:(x)对Cp语a熟?zhn)的几天就可上?/p>
热更斎ͼ(x)可以通过DLL方式q行
WebҎ(gu)Q可做,代码比较啰嗦
崩溃处理Q可通过try catch捕获错误
|络库编写难度:(x)一般,需注意gc问题
W三方网l库?qing)框架数量?x)一?/p>
开发效率:(x)?/p>
q行效率Qƈ发上非常有优势,对CPU利用率比较高Q原生运行无虚拟?/p>
部v便捷性:(x)一ơ编译到处运行,无Q何运行库依赖
调试便捷性:(x)实际操作中,单线E挂接调试器可行Q?但变量显CZ正确Q开发期基本采用日志方式q行查错
上手度:(x)语言单,Ҏ(gu)少Q?新手1周能贡献代码
热更斎ͼ(x)无法q行热更斎ͼ语言无法~译为DLLQ也不支持DLL加蝲Qlinuxq_?so加蝲忽略不计Q?/p>
WebҎ(gu)Q非常方便, 代码_
崩溃处理Q崩溃后以命令行方式打印出栈Q程序内可以捕获M崩溃错误ql运?/p>
|络库编写难度:(x)单,比C socket更简?/p>
W三方网l库?qing)框架数量?x)偏少
开发效率:(x)Z动态语a的开发初ơ写比较快,后期l护和重构会(x)耗费一定的旉在查错上
q行效率Q基于lua jit的运行效率还是能接受?/p>
部v便捷性:(x)方便Q?只有底层修改需要重新编译, 大部分时间只用更新l(f)ua文g
调试便捷性:(x)不是很方便,Z日志方式q行查错
上手度:(x)lua语言Ҏ(gu)有部分和Cp语a有一定差异,ZActor模型的思想学习(fn)Q适应需要耗费一定的旉
热更斎ͼ(x)cM于ErlangQ可_到函数的热更新
WebҎ(gu)Q有一些http支持Q通过C慢慢q行完善
崩溃处理Qlua天生可以捕获错误
|络库编写难度:(x)自带Q无需~写
W三方网l库?qing)框架数量?x)通过C慢慢完善
开发效率:(x)~译慢,文g多,通用库少
q行效率Qnative速度标杆
部v便捷性:(x)~写各类的make门槛较高
调试便捷性:(x)可通过VisualStudioq行W(xu)indowsq_调试
上手度:(x)2~3q经验的熟手仍然?x)写出崩溃和泄露代?/p>
热更斎ͼ(x)可通过DLLq行
WebҎ(gu)Q代码啰嗦,W三方库?/p>
崩溃处理QWindows下可使用SEH捕获D异常,其他q_只能通过崩溃后进行coredump分析Q容错非常差
|络库编写难度:(x)Zasio~写较ؓ(f)单,但M看来隑ֺ不低
W三方网l库?qing)框架数量?x)较多
以下是得?/p>
从发文时的项目对q些语言使用率来_(d)JavaQErlangQC++~写的服务器较多QGolangQJavaScriptQC#是第二梯队,Skynet׃上手不是很容易,所以仅有两位数的团队在使用Q但M表现q是比较?gu)?
对于老团队, C++的服务器工具铑֒框架已经相对成熟Q?完全没必要更换新语言Q?只是在对接sdk感觉困难Ӟ可以试Golangq些对web有优势的语言q行混合语言开?
对于新团队,开发效率,上手度和部v效率是优先选择的,C#QGolangQJavaScriptq些新兴语言?x)让你事半功?
对于大规模无需选服的服务器Q?Skynet的actor模型Ҏ(gu)展会(x)比较Ҏ(gu)
对于大公司,好项目,上线后需要通过热更新进行bug修补的,C#QC++QErlang?x)是首?
但ȝ一点, q是Ҏ(gu)团队熟?zhn)度来选择语言QN然的使用新语a的风险也是很大的
ZC/C++游戏服务器框架M设计的还是不错的, 兄弟们M使用效果都是好评. 因ؓ(f)在技术上喜欢"h", 所以在很多设计? 都是力求? 高效(开发效?.
Zd的异步DB查询pȝ, 带多重异步的同步
代码CZ:
1:
2: void BatchQueryPlayerInfo( uint32 ClientID, const std::string& AccountName, int64 CharID )
3: {
4: GDBExecutor->Commit
5: (
6: dynamic_cast<DBDataTask*>( (new DBQueryCharInfo( ClientID, CharID ) )
7: ->LinkAtomTask( new DBQueryQuest( ClientID, CharID ) )
8: ->LinkAtomTask( new DBQuerySkill( ClientID, CharID ) )
9: ->LinkAtomTask( new DBQueryHero( ClientID, CharID ) )
10: ->LinkAtomTask( new DBQueryAccountInfo( ClientID, AccountName ) )
11: ->LinkAtomTask( new DBQueryEquip( ClientID, CharID ) )
12: ->LinkAtomTask( new DBQueryObject( ClientID ,CharID ) )
13: ->LinkAtomTask( new DBQueryLevel(ClientID, CharID))
14: ->LinkAtomTask( new DBQueryChapter(ClientID, CharID))
15: ->LinkAtomTask( new DBQueryActivity( ClientID, CharID ))
16: )
17: );
18:
19: }
q段主要处理玩家在登陆时, 需要从DB查询大量的不同分cȝ数据. Z(jin)保证效率, 我让每个Taskq行执行, 然后通过一个机? 让所有Q务完成后, 回调W一个Q务的一个函? q样无需手动实现很多_合代码, 避免?jin)反复调试和错?/p>
Zprotobuf反射机制的语句自动合?/strong>
1: DBUpdateCharInfo::DBUpdateCharInfo( int64 CharID, const std::string& Buffer )
2: {
3: char buffer[256];
4:
5: sprintf( buffer, "update tb_char set $FIELD$ where charid = %lld;", CharID );
6:
7: ExecuteCommand( buffer, Buffer, dbopr::FET_Equation );
8: }
q段是一个典型的DBd, 构造函数提供了(jin)CharID和一个由l构体序列化好的buffer, $FIELD$字段, 是通过反射Ҏ(gu)Buffer内容, 自动填充字段
q段例子? $FIELD$可以填充?hp=100, mp=100之类? 自动填充避免?jin)因为添加字D늚到处d代码, q需要调? Ҏ(gu)搞错
配置pȝ概念
Z同一个配|系l? 分层实现不同的需? 更简单的? 解决?个实际问题是:
自己改了(jin)配置文g中的ip, 上传svn? 覆盖?jin)别人的配? 很多人的解决Ҏ(gu)都是, 本地配置不提? 但同旉题又来了(jin):
当配|中有别人新加的pȝ配置, 怎么保证每个人都能更新到?
上线? 服务器交付运l? 他们?x)对配置有一定程度的修改, q个时候怎么合ƈE序配置和运l配|?
其实对于冲突的需? 只要对系l进行分层就可以解决问题,我的处理方式:
配置分ؓ(f):
全局配置: 所有服务的M配置
单服务配|? 本服务的配置, 涉及(qing)|络?qing)逻辑
本地配置: q个配置每个Z? 不上传SVN
命o(h)行配|? 格式和前面的一? q块可以通过q维q行配置
Ml构其实是OO的派生概? 下层可以覆盖, 修改上层的配|?/p>
服务器互联及(qing)识别框架
基本功能: Z一些简单的配置可以将多台服务? 同种cȝ不同服务器互相连接v? 断线自动重连.
服务器连接后, 所有服务器可知晓ƈ可自动按需q接
逻辑端也很方便的q行q播或者单独发送等
也就是说, 每个服务器的q接和接受端都是带识别名U或id?
后面觉得q套东西实在是做的复? 多整ZC?j)服务器来? 但好Ҏ(gu)架稳定下来了(jin), 也就好了(jin).
Zlua的服务器web后台框架
思想是很不错? C++ 配合lua本nl对是个p|
问题出在web处理,本n都是一个同步阻塞过E? 而这个后台框架是异步方式来做, 所以特别别?/p>
不过比v以前的本地GMpȝ, q块的设计是伟大的进?/p>
现在正在设计Zgolang的服务器框架, 基本框架已经完工, {待~写逻辑后的实战?gu)?/p>
以上的很多思想在golang的服务器框架都有改进, 特别是golang本n做web也是优秀? 外加martiniq种牛X框架, 更是水到渠成
如果你对服务器框架设计有特别的认? 或者想撞思想, 可以加博客群 309800774或者我的qq: 20998333讨论
q是C地球上调试lua5.1最方便的工? 没有之一. 强大的注入式调试, 性能极高.支持 挂接q程, 变量展开, 断点{各U日常所需.
早期的Decoda是收费工? 因此质量非常?
Decoda现在已经停止开发ƈ开源了(jin), 调试lua5.2?x)crash. 源代码可以作ZU技术参? 很多dll注入修改技? 灰常牛X
比较优秀的调试工?因ؓ(f)收费), 可以调试lua5.1/5.2, 界面属于vs2008cd, 土豪可以考虑买几套试?/p>
对lua5.1支持较好, 5.2也能调但偶尔q是?x)crash, Zq程调试方式, 所以性能略低.
没有IDE, U命令行方式调试? 但因为简? 所以可以参考后写一个自qE序内徏调试?/p>
把这货放在最后是有原因的, q记得那句老话: 老外一开? 我们有自主研发? 对的, q货一定是参考了(jin)Decoda的代码后搞出个vs的插件来, 虽然不收? 但是不提下参考对象的行ؓ(f)q是值得Ҏ(gu)? q货在中文博客上? 不支持挂接到q程(Decoda支持), 不支?4位调?LuaStudio支持), 调试30~50ơ偶?dng)??? ? 毕竟只是代码搬运? 不生产代?
q货装上, 能用, ?.2是不行的, 5.1比Decoda方便? 毕竟vs支持(zhn)Q昄变量.
说了(jin)那么? 其实对于lua5.2版本的调? q是没有免费的比较合适的Ҏ(gu), 如果实在惌? q是可以参考下RemDebug的原理及(qing)lua官方调试文档, 自己通过c api调用写一套适合自己的远E调试工? 其实没有多复? 但L不调试的?img class="wlEmoticon wlEmoticon-smile" style="border-top-style: none; border-bottom-style: none; border-right-style: none; border-left-style: none" alt="微笑" src="http://www.shnenglu.com/images/cppblog_com/sunicdavy/Windows-Live-Writer/lua_D2A5/wlEmoticon-smile_2.png">
׃要用protoc-gen-lua, q东西生成出来的lua依然使用官方的module/package机制. 对于游戏目来说, 惌行一些自定义d, 加密{? 变得不可能. q好官方在扩展上支持的还是不错的.
参考lua5.2的官Ҏ(gu)?a title="http://www.lua.org/manual/5.2/manual.html#pdf-require" >http://www.lua.org/manual/5.2/manual.html#pdf-require
require? lua?x)自动根据一定的搜烦(ch)规律扑ֈ加蝲代码的方? q个Ҏ(gu)定义?a name="pdf-package.searchers">package.searchersq个数组? 一共有4个加载搜索顺?/p>
1. preload, 对已加蝲的moduleq行直接q回, 对应package.preload[modname]
2. lualoader, 对lua文gq行加蝲, 搜烦(ch)路径?a >package.path
3. cloader, 对lua标准dllq行加蝲, 搜烦(ch)路径?a >package.cpath
4. croot, 官方文档说的是all-in-one加蝲? 感觉很神? 感兴可以自行参考源?/p>
那么, 如果只需要自q加蝲? 只需要这样做:
package.searchers[2] = function( name ) print("try to load", name ) end package.searchers[3] = nil package.searchers[4] = nil require "libtest"只保留preload功能, 然后第二个加蝲器换成自q加蝲函数, W三,W四直接屏蔽
看qt下蝲?/a>的Qt的windows版本默认提供32位和64? 那个啥opengl版暂时未理会(x)
因ؓ(f)本hpȝ是win7 64bit, 因此毫无理由的下载了(jin)64位的qt5.2版本. ~译?jin)hello world, l果报错:
module machine type 'x64' conflicts with target machine type 'X86'
找了(jin)半天没查到错? 后面注意到vs2012的工E编译类型选择的是win32 x86, 才想h׃qt5的所有lib?4位编? 而我使用32位的E序去链? 当然要报?
重新下蝲32位的qt5.2, ~译正确
另外一个错误也是在前面版本极ؓ(f)见?
fatal error C1083: Cannot open include file: ’GLES2/gl2.h? No such file or directory
很多人的解决Ҏ(gu)是包含QtANGLE下的gles2目录, 但是׃我的工程内的cocos2dx本n也带有这东西. 于是研究?jin)下为啥q版本的qt默认要搞的非要和gles有关p?
最l? 发现可以通过定义QT_NO_OPENGL宏来屏蔽opengl的渲染API使用, ~译通过
很是怀念诺Z时代的qt, 下蝲,~译一气呵?/p>
TexturePacker的自定义插g目录位于其安装目录的bin\exporters\? 但有一些插件属于内建支? 例如cocos2dx的plist格式, 因此无法扑ֈ对应插g
本h参考shiva3d插g, 对应导出界面的DataFormat中的Shiva3D, 快速学?x)?jin)如何导出
官方文档位于http://www.codeandweb.com/texturepacker/documentation/#customization
插g的基本格式及(qing)原理?
bin\exporters\下的某一目录下存在的一个名为exporter.xml文g作ؓ(f)插g的描q?例如:
<exporter version="1.0">
<!-- identifier of the exporter -->
<name>shiva3d</name>
<!-- display name of the exporter for the combo box -->
<displayName>Shiva3D</displayName>
<!-- description of the exporter -->
<description>Exporter for Shiva3D.</description>
<!-- exporter version -->
<version>1.0</version>
<!-- currently only one file allowed - more to come with update -->
<files>
<file>
<!-- name of this file variable -->
<name>xml</name>
<!-- human readable name (for GUI) -->
<displayName>XML</displayName>
<!-- file extension for the file -->
<fileExtension>xml</fileExtension>
<!-- name of the template file -->
<template>shiva.xml</template>
</file>
</files>
<!-- target framework supports trimming -->
<supportsTrimming>false</supportsTrimming>
<!-- target framework supports rotated sprites -->
<supportsRotation>true</supportsRotation>
<!-- rotated sprites direction (cw/ccw) -->
<rotationDirection>cw</rotationDirection>
<!-- supports npot sizes -->
<supportsNPOT>true</supportsNPOT>
<!-- supports file name stripping (remove .png etc) -->
<supportsTrimSpriteNames>yes</supportsTrimSpriteNames>
<!-- supports texure subpath -->
<supportsTextureSubPath>yes</supportsTextureSubPath>
</exporter>
在Template字段? 描述同目录的导出文g格式模板. TexturePacker使用一U叫Grantlee的模板引?cM于Python使用的Django模板引擎, 文档参见:Grantlee Documentation. 单的文本格式可以参考shiva.xml快速学?/p>
q里我们使用protobuf的文本格?极ؓ(f)cMjson)导出plist, 下面是导出模?/p>
{% for sprite in allSprites %}
Sprite {
Name: "{{sprite.trimmedName}}"
FrameX: {{sprite.frameRect.x}}
FrameY: {{sprite.frameRect.y}}
FrameWidth: {{sprite.frameRectWithoutRotation.width}}
FrameHeight: {{sprite.frameRectWithoutRotation.height}}
OffsetX: {{sprite.cornerOffset.x}}
OffsetY: {{sprite.cornerOffset.y}}
OriginalWidth: {{sprite.untrimmedSize.width}}
OriginalHeight: {{sprite.untrimmedSize.height}}
{% if sprite.rotated %}Rotated: true {% endif %}
}
{% endfor %}
导出的结果类g:
Sprite {
Name: "car01"
FrameX: 100
FrameY: 129
FrameWidth: 76
FrameHeight: 47
OffsetX: 0
OffsetY: 0
OriginalWidth: 76
OriginalHeight: 47
Rotated: true
}
Sprite {
Name: "car02"
FrameX: 100
FrameY: 51
FrameWidth: 76
FrameHeight: 47
OffsetX: 0
OffsetY: 0
OriginalWidth: 76
OriginalHeight: 47
Rotated: true
}
...
导出插gq支持js扩展, 具体内容L(fng)l参考官Ҏ(gu)? 但对于简单的文本格式, q种方式已经_?/p>
Ҏ(gu)plist? 发现plist中的垃圾信息极ؓ(f)? 而且作ؓ(f)spriteframe的name居然带有扩展?.. 因此qplist,~写自己的导出插件才是王?
2. Qt的架构明显是l过_ֿ(j)设计的面向对象的。Qt因此在命名,l承Q类的组l等斚w保持?jin)优U的一致性。你只需要提供唯一一个方法的参数Q仅此一个。在不同的类中调用方式也是有很强的连贯性。返回g很有逻辑性。所有一切达C(jin)单和强大的和谐统一。一旦你使用?jin)其中一个类Q其他的cMpcL通,因ؓ(f)他们是一致的?
3. Qt不强制用Q何设计模式。如果你认ؓ(f)恰当Q用Document/view没有M问题。不使用也没有Q何问题?
4. MFC是事仉动的架构。要执行M操作Q都必须是对特定的消息作出响应。Windows对应用程序发送的信息C千计Q遗憄是,要分清楚q些分繁芜杂的消息是很困隄Qƈ且关于这斚w的文档ƈ不能很好的解册些问题?br>Qt的消息机制是建立在SIGNAL()发送和SLOT()接受的基上的。这个机制是对象间徏立联pȝ核心(j)机制。利用SIGNAL()可以传递Q何的参数。他的功能非常的强大。可以直接大传递信L(fng)SLOT()Q因此可以清楚的理解要发生的事情。一个类所发送的信号的数量通常非常的小(4或?)Qƈ且文档也非常的齐全。这让你感觉C切尽在掌握之中。SIGNAL/SLOT机制cM于Java中listener机制,不过q种机制更加轻量U,功能更齐全?
5. Qt拥有非常单而又不失强大的layout机制Q布局灉|多变
Qtq提供了(jin)一个图形用户工PQt DesignerQ可以用来帮助徏立用L(fng)面。可以修Ҏ(gu)使用的Q何控件的属性。不用将他们攑֜严格的位|,可以通过layout完美的组l他们。这个工h产生的代码我们是可以实际上阅dƈ且可以理解的。生成的代码单独攑֜一个文仉Q在~程的同Ӟ你可以随?j)所Ʋ的多次重新生成用户界面?br>Qt Designer可以让你完成许多在MFC中不可能完成的Q务,比如用预先填好的生成listviewQ在每个tab上用不同的view来用tab 控制?
6. 使用MFCQ一部分开发过E要依靠“resources?在很多的案例中开发者必M用他们。这样会(x)D如下的后果:(x)Z(jin)Visual StudioQ你很难使用其他的工h完成开发?br>资源~辑器仅有有限的功能Q比如:(x)通过Dialog~辑器不可能改变所有的属性,一些属性可以改变,另一些属性则不可能改变?译者注Q下面还有两条陈qMFC~点的实例,但我感觉q些已经够说明问题了(jin)Q暂时删节不?
然而Qtq没有资源的概念Q这p决了(jin)以上所提到的问题。Qt提供?jin)一个脚本得能编入你的代码。对于界面设计,Qt Designer则创Z(jin)可读的代码?
7. Qt的文档完备且详细的覆盖了(jin)Qt的方斚w面,竟然仅有18M。每一个类和方法都被详描qͼ巨细靡遗QD例充实。通过Trolltech公司提供的链接或者是Qt Assistant工具Q可以方便的从一个类或者方法蟩转到其他的类。文档还包含?jin)一个初学者教E和一些典型应用的例子
8. 在发布基于MFC的Y件时Q必M靠存在于客户?sh)脑上的MFC。但是这是不安全的,同样是MFC42.dllQ可以基于相同的库得?个不同的版本。通常Q需要检查是否拥有正的MFC42.dll版本Q如果不是,升U它。但是升UMFC42.dll?x)改变很多Y件的行ؓ(f)?br>Qt则没有这个风险,因ؓ(f)Qt压根没有“升U整个系l”这个概c(din)?
9. Qt 完全支持CSS2Q这使得Qt应用E序Q无论是化q是换肤Q实现v来都相当?
10. Qt自带译器,可以随意切换软g语言
在用Qt动态链接库的情况下Q根据LGPL协议规定Q是可以闭源发布M形式的程序的?
参考链接:(x)
来自Qt官方论坛的讨论:(x)http://qt-project.org/forums/viewthread/2428
博客链接Q?a >http://devbean.blog.51cto.com/448512/313477
转自:http://blog.csdn.net/superzhaifd/article/details/18224923 冬狼_Trump
本h较喜Ƣ第二点: 不用Q何设计模式构建底? 设计模式只是思想, 也是绊. 大量使用只会(x)让系l臃?
最q准备在手机目客户端中使用lua, 以前一直在服务器用luabind. 另外, tolua++也体验过, LuaPlus也在早年用过. 以下是本人对q些l定库的个h感觉:
luabind
利用boost机制把绑定做到极? 比较适合主c++, 弱lua的脚本框?
作者已l停止更? 在windows/linux~译没问? 但是在ios的LLVM? 无法~译
tolua++
像cocos2dx使用tolua++也是可以理解? 那么多函数需要绑? tolua++的头文gparse?qing)自动代码生成节U了(jin)很多手动l定的时?
但是看到代码中有一部分bugfix心(j)存不?U个人感? 本h使用不多, Ƣ迎砖头伺?,另外, tolua++只能p本层驱动C++, 而没有将已经实例化的句柄注册到l(f)ua的功能也是煞W啊
LuaPlus
接口较ؓ(f)? 适于初学者上? 无Q何的模板, 性能不高
luaBridge
目地址: https://github.com/vinniefalco/LuaBridge
手册: http://vinniefalco.com/LuaBridge/Manual.html
U头文g实现, 无需~译, 包含q入工程卛_, 接口z高?/p>
相比luabind, 唯一不能实现的常用功能就是枚? 但是可以支持cL员静(rn)态变量注? q个无所谓了(jin), 手写一个枚举支持也很简?/p>
看下演示代码:
class A { public: A( ) { } virtual void foo( int a ) { printf("foo base\n"); } std::string Member; }; class B : public A { public: virtual void foo( int a ) { printf("foo inherited\n"); } };
void foo( int b ) { }
luabridge::getGlobalNamespace(L) .beginClass<A>("Sobj") .addConstructor<void (*) (void)> () .addFunction("foo", &A::foo) .addData("Member",&A::Member) .endClass() .deriveClass<B, A>("SSec") .addFunction("foo",&B::foo ) .endClass(); luabridge::getGlobalNamespace(L).addFunction("foo", foo ); B ins; ins.Member = "data"; luabridge::setGlobal(L, ins, "ins");
lua侧的代码
local a = Sobj()
a:foo(2)
a.Member = "hello"
ins:foo(3)
error: missing binary operator before token "("
Ҏ(gu)老外的描q? boost中的BOOST_PP_ITERATION_FLAGS?.49版本后发生了(jin)一些变?
在git扑ֈ一个patch, 链接在此
以下单描q?/p>
修改call_function.hpp, call_member.hpp?qing)wrapper_base.hpp
L#elif BOOST_PP_ITERATION_FLAGS() == 1
更换?/p>
#else
#if BOOST_PP_ITERATION_FLAGS() == 1
然后在源码底部加一?endif卛_
在启动前, d如下代码:
QApplication qapp(argc, argv);
qapp.addLibraryPath(QCoreApplication::applicationDirPath()+"/plugins");
QT开发目录下: Qt\4.8.2\plugins\拯到Qt的exe目录卛_
cygwin参考这?
http://my.oschina.net/tonywolf/blog/49214
单的?
1.下蝲cygwin的网l安装包(W一ơ安装只能这?
2. 选择靠前一点的|站q行下蝲( 下好的包可以留着, 下次安装直接从文件夹中选择可以安?
cygwin下用NDK~译boost参考这?
http://blog.sina.com.cn/s/blog_a6946c8a01016aot.html
l节注意:
1. boost官网下蝲boost_1_53_0.tar.bz2, 解压攑֜android-ndk-r8e/sources?
2. 生成boost~译工具: 在boost目录下运?./bootstrap.sh 或?bootstrap.bat 生成 b2
3. 修改 boost/tools/build/v2/user-config.jam 内容修改如下
import os ;
if [ os.name ] = CYGWIN || [ os.name ] = NT {
androidPlatform = windows ;
}
else if [ os.name ] = LINUX {
androidPlatform = linux-x86_64 ;
}
else if [ os.name ] = MACOSX {
androidPlatform = darwin-x86 ;
}
modules.poke : NO_BZIP2 : 1 ;
ANDROID_NDK = ../.. ;
using gcc : android4.6 : $(ANDROID_NDK)/toolchains/arm-linux-androideabi-4.6/prebuilt/$(androidPlatform)/bin/arm-linux-androideabi-g++ :
<archiver>$(ANDROID_NDK)/toolchains/arm-linux-androideabi-4.6/prebuilt/$(androidPlatform)/bin/arm-linux-androideabi-ar
<ranlib>$(ANDROID_NDK)/toolchains/arm-linux-androideabi-4.6/prebuilt/$(androidPlatform)/bin/arm-linux-androideabi-ranlib
<compileflags>--sysroot=$(ANDROID_NDK)/platforms/android-9/arch-arm
<compileflags>-I$(ANDROID_NDK)/sources/cxx-stl/gnu-libstdc++/4.6/include
<compileflags>-I$(ANDROID_NDK)/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi/include
<compileflags>-DNDEBUG
<compileflags>-D__GLIBC__
<compileflags>-DBOOST_FILESYSTEM_VERSION=3
<compileflags>-lstdc++
<compileflags>-lgnustl_shared
<compileflags>-mthumb
<compileflags>-fno-strict-aliasing
<compileflags>-std=gnu++11
<compileflags>-O2
;
4. Z(jin)安全赯, 我打?jin)个BoostForAndriod上的补丁: 手动修改下就好了(jin)
diff -ruN boost_1_53_0-boot/boost/asio/detail/socket_types.hpp boost_1_53_0-patched/boost/asio/detail/socket_types.hpp
--- boost_1_53_0-boot/boost/asio/detail/socket_types.hpp 2012-01-15 14:46:25.000000000 +0100
+++ boost_1_53_0-patched/boost/asio/detail/socket_types.hpp 2012-06-27 19:19:01.279562338 +0200
@@ -123,7 +123,12 @@
typedef int socket_type;
const int invalid_socket = -1;
const int socket_error_retval = -1;
+// @Moss - Some platforms do not define it (Android)
+#if defined(INET_ADDRSTRLEN)
const int max_addr_v4_str_len = INET_ADDRSTRLEN;
+#else // defined(INET_ADDRSTRLEN)
+const int max_addr_v4_str_len = 16;
+#endif // defined(INET_ADDRSTRLEN)
#if defined(INET6_ADDRSTRLEN)
const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE;
#else // defined(INET6_ADDRSTRLEN)
diff -ruN boost_1_53_0-boot/boost/asio/ip/impl/address_v6.ipp boost_1_53_0-patched/boost/asio/ip/impl/address_v6.ipp
--- boost_1_53_0-boot/boost/asio/ip/impl/address_v6.ipp 2012-01-15 14:46:25.000000000 +0100
+++ boost_1_53_0-patched/boost/asio/ip/impl/address_v6.ipp 2012-06-27 19:19:11.029581297 +0200
@@ -11,6 +11,23 @@
#ifndef BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP
#define BOOST_ASIO_IP_IMPL_ADDRESS_V6_IPP
+// @Moss - Define IPv6 macros
+#if !defined(IN6_IS_ADDR_MULTICAST)
+#define IN6_IS_ADDR_MULTICAST(a) (((__const uint8_t *) (a))[0] == 0xff)
+#endif
+
+#if !defined(IN6_IS_ADDR_MC_NODELOCAL)
+#define IN6_IS_ADDR_MC_NODELOCAL(a) \
+ (IN6_IS_ADDR_MULTICAST(a) \
+ && ((((__const uint8_t *) (a))[1] & 0xf) == 0x1))
+#endif
+
+#if !defined(IN6_IS_ADDR_MC_GLOBAL)
+#define IN6_IS_ADDR_MC_GLOBAL(a) \
+ (IN6_IS_ADDR_MULTICAST(a) \
+ && ((((__const uint8_t *) (a))[1] & 0xf) == 0xe))
+#endif
+
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
diff -ruN boost_1_53_0-boot/boost/config/user.hpp boost_1_53_0-patched/boost/config/user.hpp
--- boost_1_53_0-boot/boost/config/user.hpp 2004-01-10 13:10:00.000000000 +0100
+++ boost_1_53_0-patched/boost/config/user.hpp 2012-06-27 19:18:46.129532736 +0200
@@ -13,6 +13,15 @@
// configuration policy:
//
+// Android defines
+#define __arm__ 1
+#define _REENTRANT 1
+#define _GLIBCXX__PTHREADS 1
+// There is problem with std::atomic on android (and some other platforms).
+// See this link for more info:
+// https://code.google.com/p/android/issues/detail?id=42735#makechanges
+#define BOOST_ASIO_DISABLE_STD_ATOMIC 1
+
// define this to locate a compiler config file:
// #define BOOST_COMPILER_CONFIG <myheader>
diff -ruN boost_1_53_0-boot/boost/detail/endian.hpp boost_1_53_0-patched/boost/detail/endian.hpp
--- boost_1_53_0-boot/boost/detail/endian.hpp 2011-03-29 23:58:48.000000000 +0200
+++ boost_1_53_0-patched/boost/detail/endian.hpp 2012-06-27 19:18:39.359519453 +0200
@@ -31,7 +31,7 @@
// GNU libc offers the helpful header <endian.h> which defines
// __BYTE_ORDER
-#if defined (__GLIBC__)
+#if defined (__GLIBC__) || defined(ANDROID)
# include <endian.h>
# if (__BYTE_ORDER == __LITTLE_ENDIAN)
# define BOOST_LITTLE_ENDIAN
diff -ruN boost_1_53_0-boot/boost/interprocess/detail/workaround.hpp boost_1_53_0-patched/boost/interprocess/detail/workaround.hpp
--- boost_1_53_0-boot/boost/interprocess/detail/workaround.hpp 2011-12-26 18:21:36.000000000 +0100
+++ boost_1_53_0-patched/boost/interprocess/detail/workaround.hpp 2012-06-27 19:18:52.909546004 +0200
@@ -54,7 +54,7 @@
#endif
//Check for XSI shared memory objects. They are available in nearly all UNIX platforms
- #if !defined(__QNXNTO__)
+ #if !defined(__QNXNTO__) && !defined(ANDROID)
#define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS
#endif
diff -ruN boost_1_53_0-boot/libs/filesystem/src/operations.cpp boost_1_53_0-patched/libs/filesystem/src/operations.cpp
--- boost_1_53_0-boot/libs/filesystem/src/operations.cpp 2012-01-28 15:40:16.000000000 +0100
+++ boost_1_53_0-patched/libs/filesystem/src/operations.cpp 2012-06-27 19:19:19.269597266 +0200
@@ -73,13 +73,15 @@
const fs::path dot_dot_path("..");
# include <sys/types.h>
# include <sys/stat.h>
-# if !defined(__APPLE__) && !defined(__OpenBSD__)
+# if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) && !defined(ANDROID)
# include <sys/statvfs.h>
# define BOOST_STATVFS statvfs
# define BOOST_STATVFS_F_FRSIZE vfs.f_frsize
# else
# ifdef __OpenBSD__
# include <sys/param.h>
+# elif defined(__ANDROID__) || defined(ANDROID) // @Moss - Android messes up a bit with some headers, this one is the correct one :D
+# include <sys/vfs.h>
# endif
# include <sys/mount.h>
# define BOOST_STATVFS statfs
@@ -206,7 +208,19 @@
|| ::mkdir(to.c_str(),from_stat.st_mode)!= 0))
# define BOOST_COPY_FILE(F,T,FailIfExistsBool)copy_file_api(F, T, FailIfExistsBool)
# define BOOST_MOVE_FILE(OLD,NEW)(::rename(OLD, NEW)== 0)
+#if defined(__ANDROID__) || defined(ANDROID)
+ int BOOST_RESIZE_FILE(const char *path, off_t size)
+ {
+ int result = -1;
+ int fd = open(path, O_WRONLY);
+ if (fd != -1)
+ result = ftruncate(fd, size);
+ close(fd);
+ return result;
+ }
+#else
# define BOOST_RESIZE_FILE(P,SZ)(::truncate(P, SZ)== 0)
+#endif
# define BOOST_ERROR_NOT_SUPPORTED ENOSYS
# define BOOST_ERROR_ALREADY_EXISTS EEXIST
5. 命o(h)行编?
./b2 --without-python --without-mpi --without-serialization toolset=gcc-android4.6 link=static runtime-link=static target-os=linux --stagedir=android
使用~译完成的boost?
1. 编译boost_1_53_0\android\lib\ 下的.a??qing)boost_1_53_0\boost\下的头文件拷贝出来放在工E的boost4android目录?
2. 在boost4android目录?创徏Android.mk, 内容如下
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_atomic
LOCAL_SRC_FILES:= lib/libboost_atomic.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_chrono
LOCAL_SRC_FILES:= lib/libboost_chrono.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_context
LOCAL_SRC_FILES:= lib/libboost_context.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_date_time
LOCAL_SRC_FILES:= lib/libboost_date_time.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_exception
LOCAL_SRC_FILES:= lib/libboost_exception.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_filesystem
LOCAL_SRC_FILES:= lib/libboost_filesystem.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_graph
LOCAL_SRC_FILES:= lib/libboost_graph.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_iostreams
LOCAL_SRC_FILES:= lib/libboost_iostreams.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_math_c99
LOCAL_SRC_FILES:= lib/libboost_math_c99.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_math_c99f
LOCAL_SRC_FILES:= lib/libboost_math_c99f.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_math_c99l
LOCAL_SRC_FILES:= lib/libboost_math_c99l.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_math_tr1
LOCAL_SRC_FILES:= lib/libboost_math_tr1.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_math_tr1f
LOCAL_SRC_FILES:= lib/libboost_math_tr1f.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_math_tr1l
LOCAL_SRC_FILES:= lib/libboost_math_tr1l.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_program_options
LOCAL_SRC_FILES:= lib/libboost_program_options.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_random
LOCAL_SRC_FILES:= lib/libboost_random.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_regex
LOCAL_SRC_FILES:= lib/libboost_regex.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_system
LOCAL_SRC_FILES:= lib/libboost_system.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_thread
LOCAL_SRC_FILES:= lib/libboost_thread.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= boost_timer
LOCAL_SRC_FILES:= lib/libboost_timer.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_WHOLE_STATIC_LIBRARIES += boost_system
LOCAL_WHOLE_STATIC_LIBRARIES += boost_filesystem
LOCAL_WHOLE_STATIC_LIBRARIES += boost_thread
用多? 包多?/p>
d异常支持 LOCAL_CPPFLAGS += –fexceptions
d模块引用
$(call import-module,boost4android)
文本格式的解析错误不能用捕获错误来获取, 因此,我们需要用自定义的错误收集器q行攉, 看代?
#include <google/protobuf/text_format.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <google/protobuf/io/tokenizer.h>
class PBTextErrorCollector : public google::protobuf::io::ErrorCollector
{
public:
PBTextErrorCollector( const std::string& FileName )
: mFileName( FileName )
{
}
virtual void AddError(int line, int column, const string& message)
{
CCLog("%s(%d:%d) %s ", mFileName.c_str(), line, column, message.c_str() );
}
virtual void AddWarning(int line, int column, const string& message)
{
CCLog("%s(%d:%d) %s ", mFileName.c_str(), line, column, message.c_str() );
}
private:
std::string mFileName;
};
解析代码
google::protobuf::TextFormat::Parser P;
P.RecordErrorsTo( &PEC );
P.Parse( &AIS, &AF );
另外: 文本格式的注释用unix shell风格: ?开?/p>
下面是我的文本格式的配置文g
AnchorPointX: 0.5 AnchorPointY: 0 SpriteScale: 2 ComponentName: "ActorActionManager" ComponentName: "ActorFrameEventDispatcher" #ComponentName: "SoundFXController" ComponentName: "RoleDeltaMoveController" ComponentName: "RoleBehaviorDirector" InitAction: AA_Idle Animations { AnimationName: "mai_idle" AnimationInterval: 0.067 }
在你的Android.mk文g中添?LOCAL_CPPFLAGS += -std=gnu++0x卛_
pdb加蝲是正常的, 但是堆栈没显C如此简单的I指针访问位|? Google?jin)以?/p>
解决Ҏ(gu): Debug->Exception中将所有异常勾选即?/p>
不知道哪里的讄D如此诡异的问? 害的我重装一?.
ProjectName\
src\
core\
share\
proj.android\
jni\
?/p>
sdk\
protobuf-2.4.1\
src\
?/p>
从Google code下蝲protobuf-2.4.1源码? 解压, 在protobuf-2.4.1目录下添加Android.mk, 内容如下
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := protobuf-2.4.1
LOCAL_SRC_FILES := \
src/google/protobuf/io/coded_stream.cc \
src/google/protobuf/io/printer.cc \
src/google/protobuf/io/gzip_stream.cc \
src/google/protobuf/io/tokenizer.cc \
src/google/protobuf/io/zero_copy_stream.cc \
src/google/protobuf/io/zero_copy_stream_impl.cc \
src/google/protobuf/io/zero_copy_stream_impl_lite.cc \
src/google/protobuf/stubs/common.cc \
src/google/protobuf/stubs/once.cc \
src/google/protobuf/stubs/structurally_valid.cc \
src/google/protobuf/stubs/strutil.cc \
src/google/protobuf/stubs/substitute.cc \
src/google/protobuf/compiler/importer.cc \
src/google/protobuf/compiler/parser.cc \
src/google/protobuf/descriptor.cc \
src/google/protobuf/descriptor.pb.cc \
src/google/protobuf/descriptor_database.cc \
src/google/protobuf/dynamic_message.cc \
src/google/protobuf/extension_set.cc \
src/google/protobuf/extension_set_heavy.cc \
src/google/protobuf/generated_message_reflection.cc \
src/google/protobuf/generated_message_util.cc \
src/google/protobuf/message.cc \
src/google/protobuf/message_lite.cc \
src/google/protobuf/reflection_ops.cc \
src/google/protobuf/repeated_field.cc \
src/google/protobuf/service.cc \
src/google/protobuf/text_format.cc \
src/google/protobuf/unknown_field_set.cc \
src/google/protobuf/wire_format.cc \
src/google/protobuf/wire_format_lite.cc \
LOCAL_C_INCLUDES := $(LOCAL_PATH) \
$(LOCAL_PATH)/src
include $(BUILD_STATIC_LIBRARY)
此时~译?x)报config.h找不到的错误, q个文g在vsproject目录? 但只是VC~译使用, q篇文章说需要手动创? 但实际上, Linux下可以通过configpȝ自动生成? 但是Androidq_?不用cygwin? 需要自己手动创建config.h, 内容如下
/*
This make file is only for android ONLY, modified by Davy Xu June 17, 2013
Cause android platform can't use linux config system when cygwin envirement is not available
*/
/* the location of <hash_set> */
#define HASH_SET_H <ext/hash_set>
#define HASH_MAP_H <ext/hash_map>
#define HASH_NAMESPACE __gnu_cxx
/* define if the compiler has hash_map */
//#define HAVE_HASH_MAP 1
/* define if the compiler has hash_set */
//#define HAVE_HASH_SET 1
#define HAVE_PTHREAD
剩下的事情就单了(jin), 在你的工EAndroid.mk里添加protobuf的引?/p>
例如:
LOCAL_WHOLE_STATIC_LIBRARIES += protobuf-2.4.1
$(call import-module,protobuf-2.4.1)
q要在NDK_MODULE_PATH中增加搜索\径D:\Develop\ProjectName\sdk\
注意, q里protobuf-2.4.1名称必须与sdk下的文g夹名, LOCAL_MODULE中的名称保持一? 否则搜烦(ch)不到
h意下载对应你pȝ的版? 64位系l请保证后文全系使用64位程? 以免遇到不必要的ȝ(ch)
1.JDK&JRE JAVAq行时及(qing)开发包
2.ADT 是Eclipse的一个插Ӟq一步是Z(jin)理安卓开发库
http://developer.android.com/sdk/index.html
作ؓ(f)新手, 请下载ADT Bundle For Windows, q个版本已经包含
ADKQ安卓开发包Q? CDTQEclipse的C/C++开发插Ӟ(j)?qing)对应的Eclipse, 可以避免W一ơ部|出现的各种?ch)?j)!
3.NDK 只有ADT已经可以q行普通的AndriodE序Q但是如果需要编译C/C++E序Q?q需要NDK
http://developer.android.com/tools/sdk/ndk/index.html
4. cocos2dx 2.0.4版本
准备SDK API
下蝲好ADT后解压, 有如下目?/p>
eclipse\ <- 开发环?/p>
sdk\ <- Andriod SDK
SDK Manager.exe <-- Android开发包理? ׃Andriod版本较多, 所以此理器可以方便开发者选择部v目标机器
打开SDK Manager在Android 2.2(API 8)里的 SDK Platform, Google APIs前打? 点击右下角的Instal packages
如果感觉下蝲速度? 可以ULq里http://my.oschina.net/heguangdong/blog/17443, 选择Andriodȝ下蝲
q里是下载链?/p>
http://dl-ssl.google.com/android/repository/google_apis-8_r02.zip
http://dl-ssl.google.com/android/repository/android-2.2_r02-windows.zip
https://dl-ssl.google.com/android/repository/usb_driver_r04-windows.zip
把android开头的文g解压到platforms目录?/p>
把goole_apis开头的文g解压到add-ons目录?/p>
把usb_driver_r03-windows.zip解压到usb_driver目录下?/p>
Eclipse导入工程
打开Eclipse
导入Cocos2dx例子工程:
Eclipse中File->New->Other...选择Andriod Project from Existing Code
在Import Projects的Root Directory中导入D:\Develop\RevWar\sdk\cocos2d-2.0-x-2.0.4\samples\HelloCpp\proj.android\
注意, 不要选中 Copy project into workspace, 否则路径~ؕ很难~译成功
导入cocos2dx的java框架
在src目录中new package, 输入org.cocos2dx.lib, 在org.cocos2dx.lib的package中点Import-> FileSystem
选中目录D:\Develop\RevWar\sdk\cocos2d-2.0-x-2.0.4\cocos2dx\platform\android\java\src\org\cocos2dx\lib\, 炚w所有java文g
工程Properties->Builder->New->Program
在Main标签中填?/strong>
填写NDK~译命o(h)?D:\Develop\android-ndk-r8e\ndk-build.cmd
点击Browser Workspace选中当前工程,出现${workspace_loc:/HelloCpp}
切换到Environment标签中填?/strong>
新徏NDK_MODULE_PATH 填写D:\Develop\RevWar\sdk\cocos2d-2.0-x-2.0.4\;D:\Develop\RevWar\sdk\cocos2d-2.0-x-2.0.4\cocos2dx\platform\third_party\android\prebuilt\
修改cocos2dx的Android.mk, diff如下
@@ -153,6 +153,7 @@
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_jpeg_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_libxml2_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_libtiff_static
+LOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static
# define the macro to compile through support/zip_support/ioapi.c
LOCAL_CFLAGS := -DUSE_FILE32API
@@ -164,3 +165,4 @@
$(call import-module,libpng)
$(call import-module,libxml2)
$(call import-module,libtiff)
+$(call import-module,CocosDenshion/android)
F&Q
andriod-8问题
修改D:\Develop\RevWar\sdk\cocos2d-2.0-x-2.0.4cocos2dx\platform\android\java\project.properties中的target=android-8Ҏ(gu)你需要的版本
resources.ap_ does not exist
assert目录中有资源出问? 排查卛_
例如: cocos2d-2.0-x-2.0.4\samples\TestCpp\proj.android\assets\Images\*.pvr.gz
启动Android模拟器时的Failed to allocate memory: 8问题
调整内存?h内存太大D
api版本q低DJAVA Symbol未定义问?/strong>
setEGLContextClientVersion undefined
api8(andriod 2.2)后的版本, 才支持openGL es 2.0
自己做工E遇到的问题D:\Develop\RevWar\sdk\cocos2d-2.0-x-2.0.4\/cocos2dx/platform/android/jni/JniHelper.h:28:18: fatal error: string: No such file or directory
cocos2dx例子中的Application.mk拯? 修改下内部名U即?/p>
调试请尽量用真? 模拟器速度很慢
米2默认只能理文g, 无法用adb q接, 因此需要安装驱? USB驱动直接在插入电(sh)脑后的虚拟盘里找.. q个太坑?.
保证每次都能部v最新的E序
h行每ơClean, Build project, Debug. 真机上在需要时, ?x)弹出安?..
Android启动日志
带有ADT的Eclipse中有一个logcatH口, 里面有系l及(qing)E序本n的日? 可以做过?方便(g)查问? 如需自己打日? 可以使用cocos2dx中的LOGD宏来? 原型是__android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
Remark
dassert? F5h后再~译
NDK build?默认从工E的jni目录开?
Andriod.mk的import 原则$(call import-module,模块? q里的模块名必须与目录名, 模块make file中的名称报纸一?
参考文?/strong>
http://www.cnblogs.com/ybgame/archive/2012/06/07/2540693.html
发文? Andriod Studio已经发布?jin)一D|? 虽然是测试版, 但将代表未来更方便的Andriod发布工具
~译python版的protobuf模块
?a >https://code.google.com/p/protobuf/downloads/list 下蝲官方的原生版本protobuf, q里发文时用的?.4.1版本
~译出protoc执行文g, 放一份在protobuf-2.4.1\src\?/p>
下蝲python2.7版本, 在protobuf-2.4.1\python下运行python setup.py install(如果找不到pythonL(fng)pythonl对路径)
q一? python?x)下一个蛋( 真的是一个python的egg文g ), 然后~译出python版本的protobuf模块攄在python?/p>
制作protoc-gen-lua的批处理
放一份protoc在protoc-gen-lua的plugin目录
~写批处?protoc-gen-lua.bat
@python "%~dp0protoc-gen-lua"
协议目录生成脚本
在你需要放|协议的目录~写如下批处?/p>
buildproto.bat
rd /S /Q .\%1%
"..\..\src\protoc-gen-lua\plugin\protoc.exe" --plugin=protoc-gen-lua="..\..\src\protoc-gen-lua\plugin\protoc-gen-lua.bat" --lua_out=. %1%.proto
注意protoc.exe?qing)protoc-gen-lua.bat的\径符合你的\?/p>
再编写要~译的proto协议的批处理generate.bat
call buildproto.bat loginsvc
执行generate.bat? 会(x)~译同目录下的loginsvc.proto,输出loginsvc_pb.lua
~译链接lua的pb?/strong>
protoc-gen-lua\protobuf\目录拯C前的协议目录
其下的pb.c铑օ你的工程, 注意VS2010的VC下需要修Ҏ(gu)?/p>
1.?#include <endian.h>修改?/p>
#ifndef _WIN32
#include <endian.h>
#endif
避免在windows下缺失文件报?
2. 调整struct_unpack函数前几行ؓ(f)
static int struct_unpack(lua_State *L)
{
uint8_t format = luaL_checkinteger(L, 1);
size_t len;
const uint8_t* buffer = (uint8_t*)luaL_checklstring(L, 2, &len);
size_t pos = luaL_checkinteger(L, 3);
uint8_t out[8];
buffer += pos;
避免VS2010的VC~译器过于标? 严格要求C风格函数变量前置声明
在lua_State声明后添加如下代?/p>
extern "C" { int luaopen_pb (lua_State *L);} // 注意防在命名I间外的全局声明
luaopen_pb( L ); // 直接注入全局pb, 避免动态加载pb.dll造成的一pd跨^台问?/p>
lua中用pb
local loginsvc_pb = require “loginsvc_pb”
local REQ = loginsvc_pb.CheckVersionREQ()
local Data = REQ:SerializeToString( )
local ACK = loginsvc_pb.CheckVersionACK()
ACK:ParseFromString( Data )
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
我的工程目录
script\
protobuf\
buildproto.bat
generate.bat
loginsvc_pb.lua
loginsvc.proto
Main.lua
src\
protoc-gen-lua\
example\
plugin\
protobuf\
在编写本文前, W者用过诸如libunwind{库q行错误时堆栈打? 但是其本w由于需要引用第三方? 使用q是E微ȝ(ch).
l过Google? 居然扑ֈ一?a >好文, 光过捕获SIGSEGV信号, q迫使程序进入gdb调试阶段, 利用gdb强大的调试功能可以进行各U错误跟t? 此法已与Windows下程序崩溃后弹出VC调试几乎接近.
我在此文基础? 扩展?jin)其通用性及(qing)便利?/p>
1. 使用gdb?-ex参数, 在挂接程序后, 执行bt指o(h)打出E序堆栈
2. 信息重定向到自定义的文?在多q程都需要进行后台输出时带来更大的灵zL? 同时也解决了(jin)gdb只能在前台调试的问题
代码如下
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <string.h> void dump(int signo) { char buf[1024]; char cmd[1024]; FILE *fh; snprintf(buf, sizeof(buf), "/proc/%d/cmdline", getpid()); if(!(fh = fopen(buf, "r"))) exit(0); if(!fgets(buf, sizeof(buf), fh)) exit(0); fclose(fh); if(buf[strlen(buf) - 1] == '/n') buf[strlen(buf) - 1] = '/0'; snprintf(cmd, sizeof(cmd), "gdb %s %d -ex=bt > ./a.txt", buf, getpid()); system(cmd); exit(0); }
在服务器开启时,d signal(SIGSEGV, &dump ); q行信号处理挂接卛_
引用: http://blog.csdn.net/kakaka2011/article/details/6597857 作? kakaka2011
”After a successful async_read_until operation, the streambuf may contain additional data beyond the delimiter. An application will typically leave that data in the streambuf for a subsequent async_read_until operation to examine.?/p>
意思是, streambuf中ƈ不一定是到分隔符前的所有数? 多余的数据可能一样会(x)在streambuf? 也就是说, q需要自己再ơ处理一遍数?..
动手? async_read_until看似是一个废? 底层已经费了(jin)很多CPU在逐字W与分隔W的匚w? 抛上来的数据居然q是半成?
代码如下, 试通过, 但是实在很费解ؓ(f)啥非要再做一?.
boost::asio::streambuf* SB = SBP.get(); // 讉K~冲 const char* Buffs = boost::asio::buffer_cast<const char*>( SB->data() ); uint32 DataSize = 0; for ( uint32 i = 0; i < SB->size(); ++i ) { const char DChar = Buffs[i]; // q里需要自己判断字W串内容, read_until的文档里q么说的 if ( DChar == '\0' ) { DataSize = i; break; } } if ( DataSize > 0 ) { // 取成字符?/span> std::string FullText( Buffs, DataSize ); // 消费 SB->consume( DataSize ); mWorkService->post( boost::bind(&AsioSession::NotifyReadString, shared_from_this(), FullText ) ); }
另外, Z(jin)保证输入性安? 可以在streambuf构造时加一个最大一个读取量, 过此量?x)返回报? 避免?jin)缓冲区被撑爆的危?/font>
在Windows环境变量中没有找?(QTDIR)
随即在Qt的Visual Studio 插g菜单? Qt->Qt Options-> Qt Versions
讄Default Qt/Win version为新版本
选中原有的Qt工程, 在插件菜单中扑ֈQt Project Settings->Properties->Version?版本设|ؓ(f)最新版?/p>
如果装有Visual AssitX, 此时q东西应该开始Parse新的Qt库了(jin)
have fun !
最q遇到DB服务器中报出一个MySQL的错?Commands out of sync; you can't run this command now,2014
查阅很多代码, 解决Ҏ(gu)都是使用C接口的方? 模仿其解x?在MySQL++中找C(jin)比较好的解决Ҏ(gu):
Ҏ(gu)A: 清空每次未用的记录
for (int i = 1; DataQuery.more_results(); ++i) { DataQuery.store_next(); }
其中 DataQuerycd为mysqlpp::Query
Ҏ(gu)B: 对于存储q程?使用?jin)多个select语句q回同样的列l果, 需要用以下语?/p>
static void print_multiple_results(Query& query)
{
// 执行查询q输出结果表
StoreQueryResult res = query.store();
print_result(res, 0);
for (int i = 1; query.more_results(); ++i) {
res = query.store_next();
print_result(res, i);
}
}
参考文?http://hi.baidu.com/freeknight/item/ea9fd88e7d291f854514cf43
长久以来QLisp一直被许多为史上最非凡的编E语a。它不仅?0多年前诞生的时候带来了(jin)诸多革命性的创新q极大地影响?jin)后来编E语a的发展,即在一大批C语言不断涌现的今天,Lisp的诸多特性仍然未被超。当各式各样的编E语a摆在面前Q我们可以从q行效率、学?fn)曲Uѝ社区活跃度、厂商支持等多种不同的角度进行评判和选择Q但我特别看中的一点在于语a能否有效地表辄E者的设计思想。学?fn)C意味着学习(fn)如何用过E来表达设计思想Q学?fn)Java意味着学习(fn)如何用对象来表达设计思想Q而虽然Lisp与函数式~程有很大的关系Q但学习(fn)Lispl不仅仅是学?fn)如何用函数表达设计思想。实际上Q?strong>函数式编Eƈ非Lisp的本?/strong>Q在已经掌握?jin)lambda、高阶函数、闭包、惰性求值等函数式编E概念之后,学习(fn)Lisp仍然大大加深?jin)我对编E的理解?strong>学习(fn)Lisp所收获的是如何“自由地”表达你的思想Q这正是Lisp最大的力所在,也是q门古老的语言仍然h很强的生命力的根本原因?
Lisp意ؓ(f)表处?List Processing)Q源自设计者John McCarthy?960q发表的一论文《符可辑ּ的递归函数?qing)其机器计算》。McCarthy在这论文中向我们展CZ(jin)用一U简单的数据l构S表达?S-expression)来表CZ码和数据Qƈ在此基础上构ZU完整的语言。Lisp语言形式单、内涉|刻,Paul Graham在《Lisp之根源》中其对编E的贡献与欧几里德对几何的A(ch)献相提ƈ论?
然而,与数学世界中单易懂的Ƨ氏几何形成鲜明Ҏ(gu)Q程序世界中的Lisp却一直是一U古老而又秘的存在,真正理解其精妙的是少数。从表面上看QLisp最明显的特征是它“古怪”的S表达式语法。S表达式是一个原?atom)Q或者若qS表达式组成的列表(list)Q表辑ּ之间用空格分开Q放入一Ҏ(gu)号中。“列表“这个术语可能会(x)Ҏ(gu)让h联想到数据结构中的链表之cȝUŞl构Q实际上QLisp的列表是一U可嵌套的树(wi)形结构。下面是一些S表达式的例子:
foo () (a b (c d) e) (+ (* 2 3) 5) (defun factorial (N) (if (= N 1) 1 (* N (factorial (- N 1))) ) )
据说Q这个古怪的S表达式是McCarthy在发明Lisp时候所采用的一U(f)时语法,他实际上是准备ؓ(f)Lisp加上一U被UCؓ(f)M表达?M-expression)的语法,然后再把M表达式编译ؓ(f)S表达式。用一个通俗的类比,S表达式相当于是JVM的字节码Q而M表达式相当于Java语言Q但是后来Lisp的用者都熟?zhn)q喜Ƣ上?jin)直接用S表达式编写程序,q且他们发现S表达式有许多独特的优点,所以M表达式的引入也就被无限期延迟?jin)?
许多Lisp的入门文章都比较Lisp的函数式Ҏ(gu),而我认ؓ(f)q是一U误对{真正的Lisp之门不在函数式编E,而在S表达式本w,Lisp最大的奥秘p在S表达式后面。S表达式是Lisp的语法基Q语法是语义的蝲体,形式是实质的寄托?strong>“S表达式”是E序的一UŞQ正如“七a”是诗的一UŞQ“微博”是信息的一UŞ。正是Ş的不同,让微博与博客有了(jin)质的差异Q同L(fng)道理Q正是S表达式让Lisp与C、Java、SQL{语a有了(jin)天壤之别?
一门语a能否有效地表辄E者的设计思想取决于其抽象机制的语义表达能力。根据抽象机制的不同Q语a的抽象机制Ş成了(jin)面向q程、面向对象、函数式、ƈ发式{不同的范式。当你采用某一U语aQ基本上pCZ已经“面向XXX“了(jin)Q你的思维方式和解决问题的手段׃(x)依赖于语a所提供的抽象方式。比如,采用Java语言通常意味着采用面向对象分析设计Q采用Erlang通常意味着按Actor模型对ƈ发Q务进行徏模?
有经验的E序员都知道Q无论是面向XXX~程Q程序设计都有一条“抽象原则“:(x)What与How解耦。但是,普通语a的问题就在于表达W(wng)hat的手D非常有?/strong>Q无非是q程、类、接口、函数等几种方式Q而诸多领域问题是无法直接抽象为函数或接口的。比如,你完全可以在C语言中定义若q函数来做到make file所做的事情Q但C代码很难像make file那样声明式地体现出target、depends{语义,它们只会(x)作ؓ(f)实现l节被没在一个个的C函数之中。采用OOP或是FP{其它范式也?x)遇到同L(fng)困难Q也是说make file语言所代表的抽象维度与面向q程、OOP以及(qing)FP的抽象维度是正交的,使得各种范式无法直接表达出make file的语义。这是普通语a的“刚性”特征,它要求我们必M语言的抽象维度去分析和解决问题,把问题映到语言的基本语法和语义?
更进一步,如果仔细探究q种刚性的Ҏ(gu)Q我们会(x)发现正是׃普通语a语法和语义的紧耦合造成?jin)这U刚性。比如,C语言中printf(“hello %s? name)W合函数调用语法Q它表达?jin)函数调用语义,除此之外别无他义QJava中interface IRunnable { ?}W合接口定义语法Q它表达?jin)接口定义语义,除此之外别无他义。如果你认ؓ(f)“语法和语义紧耦合“是理所当然的,看不?gu)有什么问题,那么理解Lisp׃(x)让你Ҏ(gu)产生更深的认识?
当你看到Lisp?f a (b c))的时候,你会(x)惛_什么??x)不会(x)马上联惛_函数求值或是宏扩展Q就像在C语言里看到gcd(10, 15)马上惛_函数调用Q或者在Java里看到class A马上惛_cd义一栗如果真是这P那它?yu)是你理解Lisp的一道障,因ؓ(f)你已l习(fn)惯了(jin)着语言L考,L在想q一句话机器怎么解释执行Q那一句话又对应语a的哪个特性?理解Lisp要反q来Q让语言着你,Lisp?f a (b c))可以是Q何语义,完全׃来定Q它可以是函数定义、类定义、数据库查询、文件依赖关p,异步d的执行关p,业务规则 ?
下面我准备先通过几个具体的例子逐步展示Lisp的本质。需要说明的是,׃Lisp的S表达式和XML的语法Ş式都是一U树(wi)形结构,在语义表达方面二者ƈ无本质的差别。所以,Z(jin)理解方便Q下面我暂且用多Ch更ؓ(f)熟?zhn)的XML来写代码Q请C我们可以很轻易地把XML代码和Lisp代码怺转换?
首先Q我们可以轻易地用XML来定义一个求两个数最大公U数的函敎ͼ(x) 其次Q我们可以用它来定义c:(x) q可以轻易地用它来编写关pL询:(x) q可以用它来实现cMmake file的自动化构徏(语法取自ant)Q?pre> <project name="MyProject" default="dist" basedir=".">
<property name="src" location="src"/>
<property name="build" location="build"/>
<property name="dist" location="dist"/>
<target name="init">
<mkdir dir="${build}"/>
</target>
<target name="compile" depends="init" description="compile the source " >
<javac srcdir="${src}" destdir="${build}"/>
</target>
<target name="dist" depends="compile" description="generate the distribution" >
<mkdir dir="${dist}/lib"/>
<jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/>
</target>
<target name="clean" description="clean up" >
<delete dir="${build}"/>
<delete dir="${dist}"/>
</target>
</project>
一口气举了(jin)q么多个例子Q目的在于用XMLq种?wi)Şl构来说明Lisp的S表达式所能够描述的语义。不知道你是否发C(jin)S表达式和XMLq种?wi)Ş语法在语义构造方面有着特别的“柔性”?我们可以L地用它构造出函数、变量、条件判断语义;cR属性、方法语义;可以L地构造出关系模型的select、where语义Q可以轻易地构造出make的target、depends语义Q等{数不清的语义。在普通语a里,你可以定义一个函数、一个类Q但你无法ؓ(f)C语言增加匿名函数Ҏ(gu),也没法给Java语言加上RAII语义Q甚臌自己创造一个foreach循环都不行,而自定义语义意味着在Lisp之上你创造了(jin)一门语aQ不是面向q程Q面向对象,函数式,q是关系模型Q在Lisp里统l都变成?jin)一UDSLQ而Lisp本n也就成了(jin)一U定义语a的语aQ即元语a(Meta Language)?
Lisp的柔性与S表达式有着密切的关pRLispq不限制你用S表达式来表达什么语义,同样的S表达式语法可以表辑U不同领域的语义Q这是语法和语义解?/strong>。如果说普通语a的刚性源于“语法和语义紧耦合”,那么Lisp的柔性正是源于“语法和语义解耦”!“语法和语义解耦”得Lisp可以随意地构造各U领域的DSLQ而不强制用某一U范式或是领域视角去分析和解决问题。本质上QLisp~程是一U超了(jin)普通编E范式的范式Q这是Lisp之道Q面向语a~程(LOP, Language Oriented Programming)。Wikipedia上是q样描述LOP的:(x)
Language oriented programming (LOP) is a style of computer programming in which, rather than solving problems in general-purpose programming languages, the programmer creates one or more domain-specific languages for the problem first, and solves the problem in those languages ?The concept of Language Oriented Programming takes the approach to capture requirements in the user’s terms, and then to try to create an implementation language as isomorphic as possible to the user’s descriptions, so that the mapping between requirements and implementation is as direct as possible. LOP范式的基本思想是从问题出发Q先创徏一门描q领域模型的DSLQ再用DSL去解决问题,它具有高度的声明性和抽象性。SQL、make file、CSS{DSL都可以被认ؓ(f)是LOP的具体实例,下面我们再通过两个常见的例子来理解LOP的优ѝ?
?Q在股票交易pȝ中,交易协议定义若干二进制的消息格式Q交易所和客L(fng)需要对消息q行~码和解码?
消息格式是一U抽象的规范Q本w不对语a做Q何的限制Q你可以用CQC++QJavaQ或者Python。普通的实现方式是按照消息格式规范,在相应的语言中定义消息结构,q编写相应的~解码函数。假设ؓ(f)一个消息定义结构和实现~解码函数的工作量ؓ(f)MQ不同消息类型的数量为NQ这U方式的工作量大致ؓ(f)M*N。也是说每增加一U消息类型,需要ؓ(f)该消息定义结构,实现~解码函敎ͼ引入bug的可能性当然也和M*N成正比。如果仔l观察不隑֏玎ͼ各个消息l构其实是高度类似的Q编解码函数也大同小异,但是普通语a却找不到一U抽象机制能表达q种共性,比如Q我们无法通过面向对象的方法定义一个基cL消息l构的共性抽象出来,然后让具体的消息ȝ承它Q达到复用的目的。这正是׃普通语a的抽象维度限制所_(d)在普通语a中,你只能从函数、接口等l度对事物进行抽象,而恰好消息格式共性所在的l度与这些抽象维度ƈ不匹配?
其实Q不同消息类型的共性在于它们都h相同的领域语?/strong>Q比如:(x)“某字段内容是另一个字D内容的md5码”就是一U消息格式的领域语义Q这U领域语义是OOP的抽象机制无法描q的。LOP的思\是先创徏一门消息定义DSLQ比如,cMGoogle的Protocol BufferQAndroid的AIDL。然后,通过DSL~写消息定义文gQ直接声明式地描q消息的l构特征Q比如,我们可以声明式地描述“某字段内容是另一个字D内容的md5码”。我们还需要ؓ(f)DSL开发编译器用于生成C、Java{通用语言的消息定义和~解码函数?
有了(jin)消息定义DSL和编译器之后Q由于DSL~写消息定义是一U高度声明式的编E方法,每增加一U消息的只需要多~写一个消息定义文件而已Q工作量几乎可以忽略不计。所有的工作量都集中在编译器的开发上Q工作量是一个常数CQ与消息的数量没有关p;质量保证斚w也只需要关注编译器q一点,不会(x)因ؓ(f)增加新的消息cd而引入bug?
?Q在图书理pȝ中,需要支持在理界面上对书籍、学生、班U等各种实体q行理操作?
如果按传l的三层架构Q一般需要在后端E序中ؓ(f)每一U实体定义一个类Qƈ定义相应的方法实现CRUD操作Q与之相应的Q还需要在前端面中ؓ(f)每一个实体编写相应的理面。这些实体类的CRUD操作都是大同异的,但细节又各不相同Q虽然我们很惛_用某些共同的设计实现Q但OOP所提供的封装、ѝ多态等抽象机制不以有效捕获实体之间的共性,大量的代码还是必L在子cM来完成。比如,Student和Book实体cȝ实现非常怼Q但是如果要通过OOP的方式去抽象它们的共性,得出的结果多半是Entityq样的大而空的基c,很难起到复用的效果?
其实Q不同实体之间的共性还是在于它们具有相同的领域语义Q比如:(x)实体h属性,属性具有类型,属性具有取D_(d)属性具有可d、可~辑{访问属性,实体之间有关联关pȝ。LOPҎ(gu)正是直接面向q种领域语义的。采用LOPҎ(gu)Q我们ƈ不需要ؓ(f)每一个实体类单独~写C(j)RUDҎ(gu)Q也不需要单独编写管理页面,只需要定义一UDSLq实现其~译器;然后Q用DSL声明式地~写实体描述文gQ去描述实体的属性列表,属性的cd、取D_(d)属性所支持的操作,属性之间的关系和约束条件等Q最后,通过q个实体描述文g自动生成后端的实体类和前端管理页面。采用LOPQ不论前后端采用何种技术,Java也好QC#也好QJSP也好QASP.NET也好Q都可以自动生成它们的代码。采用LOP的工作量和质量都集中在DSL的设计和~译器的开发,与实体的数量无关Q也是_(d)是庞大的系l,实体c越多越是能体现LOP的优ѝ?
通过上面两个例子我们可以感受到QLOP是一U面向领域的Q高度声明式的编E方式,它的抽象l度与领域模型的l度完全一致。LOP能让E序员从复杂的实现细节中解脱出来Q把x炚w中在问题的本质上Q从而提高编E的效率和质量?
接下来的问题是如果需要ؓ(f)某领域设计DSLQ我们是应该发明一门类似SQLq样的专用DSL呢,q是用XML或S表达式去定义DSL呢?它们各有何优~点呢?
我认为采用XML或S表达式定义DSL的优点主要有Q?) SQL、make file、CSS{专用DSL都只能面向各自的领域Q而一个实际的领域问题通常是跨多个领域的Q有时我们需要将不同领域融合在一P但是׃普通语a的刚性,多语a融合通常?x)是一仉常困隄事情Q而XML和S表达式语法结构的单一性和“代码及(qing)数据”的特点使得跨领域融合毫无障?) 在ؓ(f)DSL开发编译器或解释器的方面,二者难度不同。对XML和S表达式定义的DSLq行语法分析非常单,相比之下Q对SQLq样的专用DSLq行语法分析Q虽然可以借助Lex、Yacc、ANTLR{代码生成工P但ȝ来讲复杂度还是要明显高一些?
当然QXML和S表达式的优点也正好是其缺点,׃XML和S表达式的语法形式是固定的Q不能像专用DSL那样自由地设计语法。所以,一般来讲专用DSL的语法显得更加简z。换句话_(d)XML和Lisp其实是在语法和语义间做了(jin)一个交换,用语法的限制换来?jin)语义的灉|?
接下来我们l探讨DSL的解释执行问题。DSL代码的解释执行一般分?U典型的方式Q?) 通过专门的解释器解释执行Q?) ~译生成其他语言的代码,再通过其他语言的解释器解释执行(或编译运?Q?) 自解释。比如,W?cȝ代表是SQLQ上一节D的两个例子都属于W?c,而第3c自解释正是Lisp的特艌Ӏ?
Z(jin)理解自解释,我们可以先从内部DSL的解释执行说赗内部DSL是指嵌入在宿主语a中的DSLQ比如,Google Test单元试框架定义?jin)一套基于流畅接?Fluent Interface)的C++单元试DSL。从语义构造的角度看,内部DSL直接借用宿主语言的语法定义了(jin)自己的领域语义,是一U语法和语义解耦;从解释执行的角度看,内部DSL是随宿主语言的解释器而自动解释的Q不需要像外部DSL一样开发专门的解释器,因而实现的代h(hun)很低。当?dng)q不是说设计内部DSL不用兛_(j)M的解释实玎ͼ实际上,q是需要熟(zhn)宿主语a的特性,q利用该Ҏ(gu)得DSL能随着宿主语言的解释器得到解释执行?
Lisp拥有强大的自解释Ҏ(gu),q得益于独一无二?strong>Lisp之器Q宏 (macro) C语言中也有宏的概念,不过Lisp的宏与C语言的宏完全不同QC语言的宏是简单的字符串替换。比如,下面的宏定义Q?pre>#define square(x) (x*x)
square(1+1)的期望结果是4Q而实际上它会(x)被替换成(1+1*1+1)Q结果是3。这个例子说明,C语言的宏只在预编译阶D进行简单的字符串替换,对程序语法结构缺乏理解,非常脆弱。Lisp的宏不是单的字符串替换,而是一套完整的代码生成pȝQ它是在语法解析的基上把Lisp代码从一UŞ式{换ؓ(f)另一UŞ式,本质上vC(jin)普通语a~译器的作用。不同的是,普通编译器是把一U语a的代码{换ؓ(f)另一U语a的代码,比如QJava~译器把Java代码转换成Java字节码;而Lisp宏的输入和输出都是S表达式,它本质上是把一UDSL转换为另一UDSL。下面的例子是宏的一个典型用法?
?Q假设Lisp解释器已l具备解释执行面向过EDSL的能力,需要实现类似ant的自动化构徏工具?
我们可以Z宏构Z门类ant的DSLQ宏的作用是把类ant DSL通过宏展开变成面向q程的DSLQ最后被Lisp解释器所解释执行。这L(fng)Lisp~写的ant DSL׃需要被~译为其他语aQ也不需要像XML的ant一样依赖于专门的解释器?jin)?
当然Q和开发专门的解释?~译器相比,Lisp的宏也ƈ非没有缺点,宏难以理解,开发和调试更加困难。到底是开发专门的解释?~译器还是直接采用宏应该视具体情况而定?
Lisp采用单一的S表达式语法表达不同的语义Q实C(jin)语法和语义解耦。这使得Lisph强大的语义构造能力,擅长于构造DSL实现面向语言~程Q而宏使得Lisph自解释能力,让不同DSL之间的{换游刃有余。进入Lisp的世界应当从理解面向语言~程入门Q这是Lisp之道Q而函数式~程和宏皆ؓ(f)Lisp之器Q以道驭器方为正途?
本文是我学习(fn)Lisp的一个ȝQ也是写l有兴趣学习(fn)Lisp的程序员的入门资料。必说明,我还是一个标准的Lisp初学者,几乎没有写过像样的LispE序Q文中的错误和不_所隑օQ希望读者批评指正,感谢Q?
Why Lisp macros are cool, a Perl perspective
<func name='gcd' return_type='int'>
<params>
<a type='int'/>
<b type='int'/>
</params>
<body>
<if>
<equals>
<a/>
<int>0</int>
</equals>
</if>
<then>
<return><b/></return>
</then>
<else>
<return>
<gcd>
<modulo><b/><a/></modulo>
<a/>
</gcd>
</return>
</else>
</body>
</func>
<class name="Computer">
<field access="private" type="MainBoard" name="main-board" />
<field access="private" type="CPU" name="cpu" />
<field access="private" type="Memory" name="memory" />
<method access="public" return_type="boolean" name="powerOn" />
<params>...</params>
<body>...</body>
</method>
<method access="public" return_type="boolean" name="powerOff" />
<params>...</params>
<body>...</body>
</method>
</class>
<sql>
<select>
<column name="employees.id" />
<column name="bonus.amount" />
</select>
<from>
<table name="employees" />
<table name="bonus" />
</from>
<where>
<equals>
<column name="employees.id" />
<column name="bonus.employee_id" />
</equals>
</where>
</sql>
Lisp之器
ȝ
后记
参?/h5>
在包含中d#include <memory>卛_
mysql++版本3.1.0
q入mysql++目录,执行以下指o(h)生成libmysqlpp.a
ar rcu libmysqlpp.a mysqlpp_beemutex.o mysqlpp_cmdline.o mysqlpp_connection.o mysqlpp_cpool.o mysqlpp_datetime.o mysqlpp_dbdriver.o mysqlpp_field_names.o mysqlpp_field_types.o mysqlpp_manip.o mysqlpp_myset.o mysqlpp_mysql++.o mysqlpp_mystring.o mysqlpp_null.o mysqlpp_options.o mysqlpp_qparms.o mysqlpp_query.o mysqlpp_result.o mysqlpp_row.o mysqlpp_scopedconnection.o mysqlpp_sql_buffer.o mysqlpp_sqlstream.o mysqlpp_ssqls2.o mysqlpp_stadapter.o mysqlpp_tcp_connection.o mysqlpp_transaction.o mysqlpp_type_info.o mysqlpp_uds_connection.o mysqlpp_utility.o mysqlpp_vallist.o mysqlpp_wnp_connection.o ssqls2parse_parsev2.o
然后mv到usr/local/lib,重新链接服务器即?/p>
[root@localhost bin]# ldd wkcenter
./wkcenter: /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.11' not found (required by ./wkcenter)
./wkcenter: /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.14' not found (required by ./wkcenter)
./wkcenter: /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.9' not found (required by ./wkcenter)
./wkcenter: /lib/libc.so.6: version `GLIBC_2.9' not found (required by ./wkcenter)
./wkcenter: /lib/libc.so.6: version `GLIBC_2.7' not found (required by ./wkcenter)
./wkcenter: /lib/libc.so.6: version `GLIBC_2.8' not found (required by ./wkcenter)
./wkcenter: /lib/libc.so.6: version `GLIBC_2.11' not found (required by ./wkcenter)
linux-gate.so.1 => (0xffffe000)
liblog4cpp.so.4 => not found
libprotobuf.so.7 => not found
libboost_filesystem.so.1.48.0 => not found
libboost_system.so.1.48.0 => not found
libboost_thread.so.1.48.0 => not found
libboost_program_options.so.1.48.0 => not found
libunwind-x86.so.7 => not found
libluabind.so.0.9.0 => not found
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x008ae000)
libm.so.6 => /lib/libm.so.6 (0x0044b000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00476000)
libc.so.6 => /lib/libc.so.6 (0x002c1000)
libpthread.so.0 => /lib/libpthread.so.0 (0x0041d000)
librt.so.1 => /lib/librt.so.1 (0x00440000)
/lib/ld-linux.so.2 (0x002a2000)
上面U字部分表示glibc?qing)glibcxx库依赖不正确. 本h使用的Linux~译版本为Mint 11(ZUbuntu), 一般Ubuntu发行版的glibc配备非常? 但是上文中的发布的Linux版本为CentOS 5.8
使用/lib/libc.so.6 查看libc版本?.5, q远低于开发环境的2.11
GNU C Library stable release version 2.5, by Roland McGrath et al.
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.1.2 20080704 (Red Hat 4.1.2-51).
Compiled on a Linux 2.6.9 system on 2012-02-21.
Available extensions:
The C stubs add-on version 2.1.2.
crypt add-on version 2.1 by Michael Glad and others
GNU Libidn by Simon Josefsson
GNU libio by Per Bothner
NIS(YP)/NIS+ NSS modules 0.19 by Thorsten Kukuk
Native POSIX Threads Library by Ulrich Drepper et al
BIND-8.2.3-T5B
RT using linux kernel aio
Thread-local storage support included.
For bug reporting instructions, please see:
<http://www.gnu.org/software/libc/bugs.html>.
׃Linux操作pȝ的特有elf加蝲序. (可以参?a >此文). 虽然可以很大E度上解决Windows早期版本的dll hell问题, 但是l部|带来了(jin)很大隑ֺ
一般常见的解决Ҏ(gu)? 扑ֈ一个与目标Linux版本?qing)glibc版本一致的Linux, 代码及(qing)依赖包放在之上编? 完成后再发布.q种Ҏ(gu)与Linux下常见Y件安装方法类? 但是对于商用服务器部|步骤来说未免繁? 安全性低.
q有一U方?使用?rn)态链? 所有可执行文g文g依赖的静(rn)态库, pȝ?全部?rn)态链接到可执行文件中,可以一ơ性解册个问?/p>
步骤:
1. 在gcc链接命o(h)行中d-static -static-libgcc -static-libstdc++
2. 第三方依赖库打开?rn)态链接开? 原来链?so的库,全改为链?a
3. gcc寚w接库序很敏? 链接库顺序需要按照从前至后ؓ(f): 目产生的静(rn)态库 > W三方库?rn)态库 > pȝ?rn)态库
4. 链接? 若有未解决的symbol, 可以试在最后添?lpthread?lrt解决
在发布版本Linux上运行可能遇到的问题:
terminate called after throwing an instance of 'std::runtime_error'
what(): locale::facet::_S_create_c_locale name not valid
解决Ҏ(gu): 执行之前q行export LC_ALL="C"
另外一U获取方法是table.getn(obj), 但是q个Ҏ(gu)已经标记为废除了(jin), 量使用通用且简z的#操作W?/p>
使用lua api实现此功能就需要用到l(f)ua_objlen( ),但是q个功能未在luabind中提?所以我们顺手添加一?/p>
首先扑ֈl(f)uabind源码的object.hpp中取对象cd的type函数,在其下添加以下代?/p>
重新~译你的代码, 可以这样用luabind::obj_size( obj ) 获取对象大小?img src ="http://www.shnenglu.com/sunicdavy/aggbug/169178.html" width = "1" height = "1" />1: template<class ValueWrapper>2: inline int obj_size(ValueWrapper const& value)3: {4: lua_State* interpreter = value_wrapper_traits<ValueWrapper>::interpreter(5: value6: );7:8: value_wrapper_traits<ValueWrapper>::unwrap(interpreter, value);9: detail::stack_pop pop(interpreter, 1);10: return lua_objlen(interpreter, -1);
11: }
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:
代码? mThreadcd为lua_State*cd
GScriptScriptContext->GetVM()是加载了(jin)代码的lua_State*
StopTest为注册ؓ(f)ScriptManagedChannelcL员函数到l(f)ua中的定义
接下来看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中有个手误而造成的错? DC++代码q行到第7行时弹出assert
位于:luabind-0.9.1\luabind\detail\call_function.hpp W?64?对应以下代码W?3?/p>
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, q回的是q行错误, 但是?3行的assert挡住? 无法通过W?6行抛出异常被外面捕获.
因此,试注释W?3?/strong>, 再测? 可以在lua抛出错误? 在栈捕获到coroutine函数resume时报出的错误信息.问题解决
对于lua的coroutine, |上资料不多, q里有一比较详l的代码
我比较疑惑的? 有没有必要将代码在dofile或者dobuffer? 必须传入newthread出的state? 如果q是传入原始的state?x)有什么媄(jing)?
Ƣ迎各位有此l验的讨?/p>