colorful

zc qq:1337220912

 

static_cast与dynamic_cast转换

http://www.cnblogs.com/bastard/archive/2011/12/14/2288117.html

一 C语言中存在着两种类型转换:

隐式转换和显式转换

隐式转换:不同数据类型之间赋值和运算,函数调用传递参数……编译器完成

char ch;
int i = ch;

显示转换:在类型前增加 :(Type)变量 对变量进行的转换。用户显式增加

char *pc = (char*)pb;
void *ps = (void*)pa;


二 C++
中的类型转换

  通过这两种方式,C语言中大部分的类型转换都可以顺利进行。

至于能不能进行转换,转换后的结果如何,编译器不管需要用户自己去控制。

  C++继承了C中的隐式和显式转换的方式。但这种转换并不是安全和严格的,

加上C++本身对象模型的复杂性,C++增加了四个显示转换的关键字。(C++是强类型语言)

static_castdynamic_castconst_staticreinterpret_cast


1 static_cast

(1)用于基本的数据类型转换(char,int),及指针之间的转换

复制代码
test_enum type = test_enum_1;

char a ;
int b = static_cast<int>(a);
char c = static_cast<char>(b);
type = static_cast<test_enum>(b);

char* pa = NULL;
int *pb = (int*)pa;
//int *pb = static_cast<int*>(pa); //error
//pa = static_cast<char*>(pb) //error
char *pc = (char*)pb;
//char *pc = static_cast<char*>(pb); //error

void *p = static_cast<void*>(pa);
pb = static_cast<int*>(p);
pc = static_cast<char*>(p);
复制代码


(2)类层次中基类与子类成员函数指针的转换

 

复制代码
class A
{

public:
void set(){}
};

class B:public A
{
public:
void set(){}
};

typedef void (A::*PS_MFunc)();   //指向类A的成员函数指针

PS_MFunc func = &A::set;
func = static_cast<PS_MFunc>(&B::set); //基类指向子类成员函数指针,必须进行转换
复制代码


(3)类层次结构中基类与子类指针或引用之间的转换  

   上行转换:子类指针或引用转换成基类表示——安全

  下行转换:基类指针或引用转换成子类表示——危险(没有动态类型检查)

复制代码
class A
{
};
class B:public A
{
};
class C:public A
{
};
class D
{
};

A objA;
B objB;
A* pObjA = new A();
B* pObjB = new B();
C* pObjC = new C();
D* pObjD = new D();

objA = static_cast<A&>(objB); //转换为基类引用
objA = static_cast<A>(objB);

objB = static_cast<B>(objA); //error 不能进行转换

pObjA = pObjB; //right 基类指针指向子类对象
//objB = objA; //error 子类指针指向基类对象
pObjA = static_cast<A*>(pObjB); //right 基类指针指向子类
pObjB = static_cast<B*>(pObjA); //强制转换 OK 基类到子类
//pObjC = static_cast<C*>(pObjB); //error 继承于统一类的派生指针之间转换
//pObjD = static_cast<D*>(pObjC); //error 两个无关联之间转换
复制代码


2 dynamic_cast

(1)继承关系的类指针对象或引用之间转换

        

复制代码
class A
{
};
class B:public A
{
};
class C:public A
{
};
class D
{
};

A objA;
B objB;
A* pObjA = new A();
B* pObjB = new B();
C* pObjC = new C();
D* pObjD = new D();
//objA = dynamic_cast<A>(objB); //error 非引用

objA = dynamic_cast<A&>(objB);
//objB = dynamic_cast<B&>(objA); //error A 不是多态类型不能转换 若有虚函数则可以进行转换

pObjA = dynamic_cast<A*>(pObjB);
//pObjB = dynamic_cast<B*>(pObjA); //error A 继承关系 不是多态类型不能转换
//pObjB = dynamic_cast<B*>(pObjC); //error C 兄弟关系 不是多态类型不能转换
//pObjB = dynamic_cast<B*>(pObjD); //error D 没有关系 不是多态类型不能转换
复制代码

 

 

(2)包含有虚函数之间对象指针的转换   

复制代码
class A
{
Public:
Virtual ~A(){}
};
class B:public A
{
};
class C:public A
{
};
class D
{
Public:
Virtual ~D(){}
};
pObjB = dynamic_cast<B*>(pObjA);    // worning 继承关系 父类具有虚函数 多态
pObjB = dynamic_cast<B*>(pObjD); //worning 没有关系 D是多态类型可以转换
//以上结果:pObjB == NULL 此处会发生一个运行时错误
复制代码

         也就是说除了基类指针指向子类对象,可以没有虚函数外,其它要进行dynamic_cast转换必须具有虚函数才行。

那这是为什么呢?下面继续>


(3)dynam_cast转换的安全性

         dynamic_cast是动态转换,只有在基类指针转换为子类指针时才有意义。

(子类指针转换为基类指针本来就是可以的:基类指针指向子类对象OK)。

但是基类指针转换为子类指针,并不是每一次都有效:只有基类指针本身指向的是一个派生类的对象,

然后将此基类指针转换为对应的派生类指针才是有效的。这种情况在表面上是无法判定的。此时dynamic就发挥了作用。

情况1: static_cast转换       

复制代码
class A
{
};
class B:public A
{
public:
int m; //B 成员
};


A* pObjA = new A();
B* pObjB = NULL;
pObjB = static_cast<B*>(pObjA); //基类指针转化为子类指针 成功转换
pObjB->m = 10;   //实际中pObj所指向的对象 是A类对象
//上面会发生什么呢,在VC6.0中正常运行。。。?

//如果:

pObjB = dynamic_cast<B*>(pObjA); //error 基类A没有虚函数 不构成多态
复制代码

情况2:     dynamic_cast转换    

复制代码
class A
{
public:
virtual ~A(){} //虚函数 多态
};

class B:public A
{
public:
int m;
};

A* pObjA = new A();
B* pObjB = NULL;
pObjB = dynamic_cast<B*>(pObjA); //编译通过
//实际运行结果:pObjB == NULL // dynamic_cast保证转换无效 返回NULL
复制代码

         dynamic_cast转换不成功,则返回0

4 虚函数对于dynamic_cast转换的作用

  为何使用dynamic_cast转换类指针时,需要虚函数呢。

Dynamic_cast转换是在运行时进行转换,运行时转换就需要知道类对象的信息(继承关系等)。

如何在运行时获取到这个信息——虚函数表。

  C++对象模型中,对象实例最前面的就是虚函数表指针,

通过这个指针可以获取到该类对象的所有虚函数,包括父类的。

因为派生类会继承基类的虚函数表,所以通过这个虚函数表,我们就可以知道该类对象的父类,在转换的时候就可以用来判断对象有无继承关系。

  所以虚函数对于正确的基类指针转换为子类指针是非常重要的。

posted @ 2015-01-13 17:14 多彩人生 阅读(277) | 评论 (0)编辑 收藏

lua意见

table for循环的例子,这么一个明显的坑,都没人作一个提醒,这样肯定不利于一门语言的推广与发展

posted @ 2015-01-13 10:54 多彩人生 阅读(859) | 评论 (0)编辑 收藏

COCOS2DX,LUA,学习笔记

http://blog.sina.com.cn/s/blog_4ceb1a410101d4tq.html

以下大部分来自网络,只做学习记录用。

一 框架层面
二 Lua层面
三 工具层面
四 android打包

一 框架层
整体来说,cocos2dX提供的一个简便的框架,包含了渲染,动画,事件分发,网络还有UI,物理引擎等几大模块。对于做一个游戏从功能上来说已经
足够了。我从这几个方面分别探讨下cocos2dX的优缺点以及我们在项目中是如何用到的

(1)渲染:渲染这块,他的渲染数据跟Sprite进行了绑定,然后对于openGl也是直接进行了调用,而不是采用策略或者插件进行调用。对于后期如果采用DX的话

我觉得这块比较冗余些。但是这些并不会影响游戏的渲染速度。它提供了batch来进行批次渲染。所以在游戏里,我们对资源进行了分组,然后分别用textPacker

拼成一张图片,格式呢 没有alpha的采用 RGB565,有alpha的采用RGBA4444,要求高的话就采用RGBA8888,然后统一采用批次渲染。游戏的速度会提升很多。

对于游戏数据的管理,cocos采用CCTextureCache这个单例类进行管理。释放可以采用全部释放,还有释放没有用过的。并且也提供了异步加载动画资源的方法

(PS:这个对于想做ARPG的同学来说,可是好东西了)。所以对于渲染这块,我们尽量用批次,然后记得释放内存就OK了。

(2)动画:cocos他提供了一套action机制。整体来说,是sprite run action。然后驱动action里面的动画数据,进行播放动画。所有的动画都可以走action

接口。对于使用者来说,也不用去关心其他东西,只需要初始化好你想要的动作,然后把动作数据塞给action。然后让sprite run 就可以了。大概action就是这个

流程。本来我们想自己写自己的动画,但是到后期,因为自己写一套工作量大。所以对于move,scale什么的仍旧采用cocos自己的。只有animation采用了我们的。

但是现在想起来,完全没有必要。cocos提供的已经足够了。我们所需要做的就是把动作编辑器导出的动画数据用cocos的动作翻译(对于动作编辑器我后面会讲)写
这么一个层就好

(3)事件分发:cocos对于事件分发这块就比较弱了。他是事件管理是通过存储每一个object以及他接收事件的优先级。然后进行分发。但是他并没有对场景进行树的管理

。所以我们的改变就是建立起场景树,然后事件分发先从场景顶端往下分发。期间每个节点可以设置是否响应以及是否继续往下传递的属性(作为OC出身,这块完全模仿苹果那套)

完全丢弃了cocos的那一套事件分发机制。对于场景树的维护,只需要每次step的时候更新下。所以对于查询性能需要好好写一下
(4)网络:cocos提供了对curl的封装。提供了http的一些简单比如get,post的封装。但对于断点续传等并没有封装。对于socket,cocos则完全没有提供。我们采用了

BSDSocket

(5)UI:UI这边,cocos提供了几种简单的控件,比如CCButton等。他们都继承于CCSprite,但是太少。而且初始化方法是在是太过于奇葩。所以我们自己写了一套UI。

(其实无非也就是 button,label,tableView,scrollView,image还有textInput)他们也都继承CCSprite。然后加入一些每个控件独有的逻辑就可以了。最麻烦

的应该就是textInput了。照着cocos提供的input写一遍,然后改改。(cocos提供了CCEditeBox,但是这货的的解决办法是在IOS上调用IOS的的控件。但是他是直接加到了egLView上,对于页面移动,页面关闭处理起来比较麻烦。
所以这个暂时还不能用)

二 lua
为了让游戏更有灵活性,cocos提供了lua。由C++做引擎,然后lua去写逻辑。这样就可以绕开苹果的审核。我们就讨论下C++与lua碰到的问题。

(1)通讯:cocos采用了tolua++来进行C++与lua的通讯。看Cocos2dXLuaLoad文件里,那些就是lua与C++通讯的一个层。具体通讯原理比如是通过

栈,什么的我就不讲了(其实我也不太懂)。这些东西tolua++都已经替咱封装好了。我们需要做的就是写好C++文件
然后生成load文件。在CCLuaEngine里调用你生成的那个load方法。lua就可以访问C++了。需要说明的是,我们这边尽量是lua调用C++的方法,C++不会去调用
Lua的方法。调用也是通过callBack去调用。

(2)问题:
问题1.当C++里面的函数需要传递lua指针时:在C++里,lua的函数指针是一个int的变量。生成时用Lua_Func来代替。然后生成后执行cocos2dX源码

里面build.xml。xml的左右就是定制tolua++的生成。在里面把lua的函数指针转成了int了。具体的看xml内容就可以了。
问题2.在CCLuaEngine里调用那些load方法时,是有顺序的。一定要父类在前,子类在后。不然子类就无法访问父类的方法。

(3)写法:
lua都要加入module,变成模块化,提高代码的可读性,然后require的时候一定要像cocos例子那样,写全路径。不然打包android的时候
就悲剧了。

lua里面不要用全局变量持有sprite等C++数据。每个模块也要像cocos那样提供2个方法,一个是进入该模块的初始化方法,一个是退出
该模块的销毁方法。

对于lua这边写法,我们参考了 moai,还有corona,在lua那边在封装下C++,其他lua不是直接调用C++,尽量不要让lua的写法太过于
活跃。不然以后调试真心头大。

(4)调试:lua的调试是最大的问题。仅凭一个lua_error所报错的信息是完全不够的。而且Xcode对于lua的语法高亮支持的也不好。我们对此
进行了2方面的尝试

1.windows下,用decoda。然后也可以打断点。

2.mac下,暂时用Eclips加lua插件进行写lua,然后通过log进行调试。不过最近想尝试Vim,应该会比之前靠谱。

三 工具层面
工具上,cocos提供了 cocosBuilder,我觉得他属于一个集成的工具。想要追求全,必然不精。所以cocosBuilder不管是
场景编辑,界面编辑,还是动作编辑都不是很好用。所以我们采用的策略是用Flash的那一套。界面编辑用FlexBuilder的界面编辑,然后
导出xml,写一个xml翻译类,根据xml创建面板,动作编辑用FlashPro。然后用jsfl读出flash信息,导出xml,用cocos自己的action机制
去翻译,演绎。场景编辑的话,我们的游戏并没有用场景编辑的需求,所以没有进行研究,不过titleMap是个不错的选择

四 andrid打包
android打包,其实难点在于调试。因为无法打断点。本来lua就难调试,结果还要加上android。打包android那边就是多看看NDK,JNI的
一些资料,然后了解mk文件怎么书写。看看cocos提供的那些sh脚本。打包大部分问题都是路径的问题。根据错误一步步来,别急,肯定能打上。

打包完成以后,剩下就是调试。调试的话主要就是C++与java之间的通讯了。那就要多看看jni的一些东西。然后看cocos/platform/ 还有android

里面的类。那些是c++跟java通讯的类。我们调试主要就在那打log。jni的原理我就不讲了。。多看看懂一点就可以了。毕竟咱只是为了看懂,会照猫画虎

写一点。没必要深究。对了,android好奇葩,上网还需要权限配置!!!在mainfest.xml配置权限。靠,搞了好久这个问题。


好了,我对于cocos的见解就这么些。可能包含了cocos所有的东西吧。都不细,只是给大家当一个消遣时间的东西。欢迎大家一起讨论。
最后,感谢cocos2dX的那些大牛们。是你们的无私让我们才有机会这么容易接近游戏开发。谢谢你们

posted @ 2015-01-01 17:12 多彩人生 阅读(1059) | 评论 (0)编辑 收藏

Lua的sleep函数

一个不幸的消息是Lua中没有内置sleep函数,我们需要DIY。有4种方法可以实现sleep函数,如下:

方法1

--在一个死循环中设置一个跳出条件,但是这样的做法会占用大量CPU资源,强烈不推荐使用哦

function sleep(n)

   local t0 = os.clock()

   while os.clock() - t0 <= n do end

方法2

--调用系统的sleep函数,不消耗CPU,但是Windows系统中没有内置这个命令(如果你又安装Cygwin神马的也行)。推荐在Linux系统中使用该方法

function sleep(n)

   os.execute("sleep " .. n)

方法3

--虽然Windows没有内置sleep命令,但是我们可以稍微利用下ping命令的性质

function sleep(n)

   if n > 0 then os.execute("ping -n " .. tonumber(n + 1) .. " localhost > NUL") end

方法4

--使用socket库中select函数,可以传递0.1给n,使得休眠的时间精度达到毫秒级别。

‍require("socket")

function sleep(n)

   socket.select(nil, nil, n)

posted @ 2015-01-01 16:59 多彩人生 阅读(1360) | 评论 (0)编辑 收藏

用Cocos Code IDE写Lua,如何与项目中的C++代码和谐相处

http://segmentfault.com/blog/hongliang/1190000000628902

1、在用Cocos Code IDE建立新的cocos2d-x项目时,最好选中Add Native Codes这个选项,只有选中了它,项目目录里才会有frameworks目录,里面才会有AppDelegate.cpp等重要的C++类(程序真正的入口)。如果不勾选这个,则Cocos Code IDE使用的是默认编译好的PrebuiltRuntimeLua.app程序,日后如果要更改C++部分的程序逻辑,还是需要frameworks目录中的源代码才行,所以建议Cocos Code IDE应该把Add Native Codes这个选项默认为选中状态才对。

Cocos Code IDE新建工程时最好选中Add Native Codes

2、如果之前建立项目时没有勾选Add Native Codes,也可以随时通过右键菜单->Cocos Tools->Add Native Codes Support给补回来。

Cocos Code IDE添加Native Codes

3、有了frameworks/runtime-src/Classes目录,就可以去修改AppDelegate.cpp等C++文件了。简单修改一下,打印个log看看:

简单修改AppDelegate.cpp

4、C++文件修改好了,需要编译才能使修改生效,最简单的办法是在Cocos Code IDE中通过右键菜单->Cocos Tools->Build Custom Runtimes,选中Build Mac Runtime即可。

Cocos Code IDE Build Mac Runtime

Cocos Code IDE Build Mac Runtime

5、编译完成后,感兴趣的话就能在runtime/mac目录下看到多了一个CocosLuaGame.app程序包,这就是刚刚编译生成的Mac程序,以后每次frameworks目录下的C++文件有修改都需要再编译一次。

cocos2d-x编译后的程序都在runtime/目录下

6、使用Cocos Code IDE的Build Custom Runtimes功能后,感兴趣的话就会发现当前项目的Debug Configurations发生了变化,之前的Select Runtime中执行的程序是PrebuiltRuntimeLua.app,现在已经被自动改成了新编译出来的CocosLuaGame.app程序。这一步是Cocos Code IDE自动做的,而且非常重要,如果不更改这个选项的话,会导致调试时仍然执行的是旧的C++代码,新修改的代码无法起作用。

Cocos Code IDE的Debug选项要选中正确的启动程序

7、如果修改C++文件比较频繁,使用Cocos Code IDE的右键菜单来编译还不如直接在命令行下敲命令快:

cocos compile -p mac

注意,如果始终使用命令行来编译,从来没用过Cocos Code IDE的右键菜单,那么需要手工修改Debug ConfigurationsSelect Runtime,确保调试时启动的是CocosLuaGame.app

8、现在来启动一下,可以看到C++文件中修改的代码已经生效了:

修改后的AppDelegate.cpp文件起作用了

posted @ 2014-12-30 11:19 多彩人生 阅读(444) | 评论 (0)编辑 收藏

cocos2dx3.2 lua学习

官方网站永远是个不错的地方:
  http://cn.cocos2d-x.org/
  http://cn.cocos2d-x.org/tutorial/lists?id=82

现在主流c++ + lua开发, 主要是lua更新的优势

新建lua项目
lua项目有两个模板,lua-template-default和lua-timeplate-runtime,
可以用cocos new 命令,也可以用cocos code ide.
用cocos new 命令创建lua工程
指定用runtime模板
cocos new -p com.game.zc -l lua -t runtime -d e:/project helloLua
使用default模板
cocos new -p com.game.zc -l lua -d e:/project helloLua

用Cocos Code IDE 创建lua工程
code ide 用的是runtime模板, 创建工程时记得选中"添加C++代码", 这样会在工程目录下生成frameworks文件夹,里面是c++层的代码

Lua 调用自定义c++类
http://cn.cocos2d-x.org/tutorial/show?id=1749
http://cn.cocos2d-x.org/tutorial/show?id=1555
http://cn.cocos2d-x.org/tutorial/show?id=1295
在移植android时,需要修改frameworks\cocos2d-x\cocos\scripting\lua-bindings\Android.mk文件
将自定义的c++类文件添加到LOCAL_SRC_FILES, 文件所在目录添加到LOCAL_C_INCLUDES
如果是用Cocos Code IDE开发,
c++文件修改后,需要在Cocos Code IDE 里执行如下操作才能生效, 项目右击-->cocos 工具-->构建自定义Runtime

关于移植,
1/ 可先用cocos compile -p android 编译项目,打包时再用eclipse来打包
2/ 使用Cocos Code IDE 很方便, 项目右击-->cocos 工具-->为Android打包apk

----遇到的错误------------------------------
1
http://www.cocoachina.com/bbs/read.php?tid=234772
问题: LibclangError: [Error 193] %1 不是有效的 Win32. To provide Config.set_library_path() or Config.set_library_file().

原因:Python、pyyaml、pyCheetah都用32位版本(ps:tolua目录下README.mdown里有下载链接)
如果还不行的话,就去github上下载最新的bindings-generator(平ps:下载地址: https://github.com/guojian822/bindings-generator)



posted @ 2014-12-25 16:20 多彩人生 阅读(2413) | 评论 (0)编辑 收藏

使用cocos compile -p android时总是报错误 BUILD FAILED \ant\build.xml:892

http://www.cocoachina.com/bbs/read.php?tid=215700

错误如下。。。但是使用eclipse生成apk包时不收影响。。

-dex:
      [dex] input: E:\cocos\Mine\frameworks\runtime-src\proj.android\bin\classes
      [dex] input: E:\cocos\Mine\frameworks\js-bindings\cocos2d-x\cocos\platform\android\java\bin\classes.jar
      [dex] Pre-Dexing E:\cocos\Mine\frameworks\js-bindings\cocos2d-x\cocos\platform\android\java\bin\classes.jar -> classes-022efb48739f8be18b60e7464733537d.jar
      [dex] Converting compiled files and external libraries into E:\cocos\Mine\frameworks\runtime-src\proj.android\bin\classes.dex...
       [dx]
       [dx] UNEXPECTED TOP-LEVEL EXCEPTION:
       [dx]com.android.dx.util.DexException: Multiple dex files define Lorg/cocos2dx/lib/Cocos2dxAccelerometer;
       [dx]     at com.android.dx.merge.DexMerger.readSortableTypes(DexMerger.java:592)
       [dx]     at com.android.dx.merge.DexMerger.getSortedTypes(DexMerger.java:550)
       [dx]     at com.android.dx.merge.DexMerger.mergeClassDefs(DexMerger.java:531)
       [dx]     at com.android.dx.merge.DexMerger.mergeDexBuffers(DexMerger.java:168)
       [dx]     at com.android.dx.merge.DexMerger.merge(DexMerger.java:186)
       [dx]     at com.android.dx.command.dexer.Main.mergeLibraryDexBuffers(Main.java:300)
       [dx]     at com.android.dx.command.dexer.Main.run(Main.java:232)
       [dx]     at com.android.dx.command.dexer.Main.main(Main.java:174)
       [dx]     at com.android.dx.command.Main.main(Main.java:91)
       [dx]

BUILD FAILED
E:\BST\adt-bundle-windows-x86-20130917\sdk\tools\ant\build.xml:892: The following error occurred while executing this line:
E:\BST\adt-bundle-windows-x86-20130917\sdk\tools\ant\build.xml:894: The following error occurred while executing this line:
E:\BST\adt-bundle-windows-x86-20130917\sdk\tools\ant\build.xml:906: The following error occurred while executing this line:
E:\BST\adt-bundle-windows-x86-20130917\sdk\tools\ant\build.xml:284: null returned: 2

---------------------------
查资料发现,发现:
cocos compile 的脚本里会自动把“frameworks\js-bindings\cocos2d-x\cocos\platform\android\java\bin\classes.jar”(2dx的java代码)添加到classes.dex中。
而当用eclipse打开android项目时,默认是没有引入2dx的java类的,此时如果想正常运行android项目,需要引入2dx的jar包,或者引入2dx的java源码。
如 果引入java的源码,当再次执行“cocos compile”时,2dx的java源码生成的class文件,会跟默认引入的“frameworks\js-bindings\cocos2d-x \cocos\platform\android\java\bin\classes.jar”发生冲突,会报 “com.android.dx.util.DexException: Multiple dex files define ……”的错误;
如 果不引入java源码,而是直接在“Build path”中引入了jar包(位于引擎的:frameworks\js-bindings\cocos2d-x\cocos\platform \android\java\bin\下的classes.jar),此时android的项目不报错了,但是直接使用eclipse生成apk包时会发 现安装到手机上无法运行,这是因为项目需要的2dx文件没有被打入到apk中。此时,可以将对应的jar包放到android项目的libs目录里 (frameworks\runtime-src\proj.android\libs\),这样生成的apk包就可以正常运行了。
但是,如果这样做了,再次执行“cocos compile”时,发现还会报如上的错误,这是因为脚本里会默认将libs目录里的文件添加到classes.dex中。

综上所述:
出现如上错误的原因是在使用“cocos compile”脚本时,2dx文件被重复添加了。
不过,如果像我这样操作,使用“cocos compile”编译脚本(主要是因为该脚本会将js文件和资源拷贝的android项目里),使用eclipse将android项目打包成apk,可以忽略如上问题的;感觉很不爽。。。。

-------------解决方法
注释掉project.properties文件中的#android.library.reference.1=../cocos2d/cocos/platform/android/java就可以啦!!!

posted @ 2014-12-25 12:10 多彩人生 阅读(11360) | 评论 (0)编辑 收藏

python处理带空格目录

http://www.pylife.net/?p=159

给python的带空格目录给搞了俩钟头,我实在郁闷的不行,我想到我的同行们不能跟我一样这么郁闷,我blog被google收录的还挺快,如果你搜索标题上面的文字,基本上都能搜到。
原来的程序是这样的:
一个小小的新建:
os.system(r"mkdir %s"%(dirname))
比如你要是新建一个:C:\Program Files\Adobe\
这个时候问题就出来了,python的该命令只会新建:C:\Program,空格后面的东西全部去掉了。
问题已经出来了
0-------------------------------------------------------------------------------------------------------------------------------------------------0
解决:
r'mkdir "%s"' % (dirname)
其中%s两边的是双引号,不能是单引号,这个是跟最后的命令的形成有关系,命令中可以存在双引号或者没有引号,但是不能是单引号
这样,新建目录的时候就会全部包含起来了,不会有空格的断代。
这让我fuck python,love python

posted @ 2014-12-23 17:50 多彩人生 阅读(778) | 评论 (0)编辑 收藏

一些不错的博客


http://www.cnblogs.com/stephen-liu74/

posted @ 2014-12-19 19:19 多彩人生 阅读(175) | 评论 (0)编辑 收藏

一个很不错的lua教程

http://www.cnblogs.com/stephen-liu74/category/360139.html

  Lua可以调用C函数的能力将极大的提高Lua的可扩展性和可用性。对于有些和操作系统相关的功能,或者是对效率要求较高的模块,我们完全可以通过C函数 来实现,之后再通过Lua调用指定的C函数。对于那些可被Lua调用的C函数而言,其接口必须遵循Lua要求的形式,即typedef int (*lua_CFunction)(lua_State* L)。 简单说明一下,该函数类型仅仅包含一个表示Lua环境的指针作为其唯一的参数,实现者可以通过该指针进一步获取Lua代码中实际传入的参数。返回值是整 型,表示该C函数将返回给Lua代码的返回值数量,如果没有返回值,则return 0即可。需要说明的是,C函数无法直接将真正的返回值返回给Lua代码,而是通过虚拟栈来传递Lua代码和C函数之间的调用参数和返回值的。这里我们将介 绍两种Lua调用C函数的规则。
    1. C函数作为应用程序的一部分。
复制代码
 1 #include <stdio.h>  2 #include <string.h>  3 #include <lua.hpp>  4 #include <lauxlib.h>  5 #include <lualib.h>  6   7 //待Lua调用的C注册函数。  8 static int add2(lua_State* L)  9 { 10     //检查栈中的参数是否合法,1表示Lua调用时的第一个参数(从左到右),依此类推。 11     //如果Lua代码在调用时传递的参数不为number,该函数将报错并终止程序的执行。 12     double op1 = luaL_checknumber(L,1); 13     double op2 = luaL_checknumber(L,2); 14     //将函数的结果压入栈中。如果有多个返回值,可以在这里多次压入栈中。 15     lua_pushnumber(L,op1 + op2); 16     //返回值用于提示该C函数的返回值数量,即压入栈中的返回值数量。 17     return 1; 18 } 19  20 //另一个待Lua调用的C注册函数。 21 static int sub2(lua_State* L) 22 { 23     double op1 = luaL_checknumber(L,1); 24     double op2 = luaL_checknumber(L,2); 25     lua_pushnumber(L,op1 - op2); 26     return 1; 27 } 28  29 const char* testfunc = "print(add2(1.0,2.0)) print(sub2(20.1,19))"; 30  31 int main() 32 { 33     lua_State* L = luaL_newstate(); 34     luaL_openlibs(L); 35     //将指定的函数注册为Lua的全局函数变量,其中第一个字符串参数为Lua代码 36     //在调用C函数时使用的全局函数名,第二个参数为实际C函数的指针。 37     lua_register(L, "add2", add2); 38     lua_register(L, "sub2", sub2); 39     //在注册完所有的C函数之后,即可在Lua的代码块中使用这些已经注册的C函数了。 40     if (luaL_dostring(L,testfunc)) 41         printf("Failed to invoke.\n"); 42     lua_close(L); 43     return 0; 44 }
复制代码

    2. C函数库成为Lua的模块。
    将包含C函数的代码生成库文件,如Linux的so,或Windows的DLL,同时拷贝到Lua代码所在的当前目录,或者是LUA_CPATH环境变 量所指向的目录,以便于Lua解析器可以正确定位到他们。在我当前的Windows系统中,我将其copy到"C:\Program Files\Lua\5.1\clibs\",这里包含了所有Lua可调用的C库。见如下C语言代码和关键性注释:

复制代码
 1 #include <stdio.h>  2 #include <string.h>  3 #include <lua.hpp>  4 #include <lauxlib.h>  5 #include <lualib.h>  6   7 //待注册的C函数,该函数的声明形式在上面的例子中已经给出。  8 //需要说明的是,该函数必须以C的形式被导出,因此extern "C"是必须的。  9 //函数代码和上例相同,这里不再赘述。 10 extern "C" int add(lua_State* L)  11 { 12     double op1 = luaL_checknumber(L,1); 13     double op2 = luaL_checknumber(L,2); 14     lua_pushnumber(L,op1 + op2); 15     return 1; 16 } 17  18 extern "C" int sub(lua_State* L) 19 { 20     double op1 = luaL_checknumber(L,1); 21     double op2 = luaL_checknumber(L,2); 22     lua_pushnumber(L,op1 - op2); 23     return 1; 24 } 25  26 //luaL_Reg结构体的第一个字段为字符串,在注册时用于通知Lua该函数的名字。 27 //第一个字段为C函数指针。 28 //结构体数组中的最后一个元素的两个字段均为NULL,用于提示Lua注册函数已经到达数组的末尾。 29 static luaL_Reg mylibs[] = {  30     {"add", add}, 31     {"sub", sub}, 32     {NULL, NULL}  33 };  34  35 //该C库的唯一入口函数。其函数签名等同于上面的注册函数。见如下几点说明: 36 //1. 我们可以将该函数简单的理解为模块的工厂函数。 37 //2. 其函数名必须为luaopen_xxx,其中xxx表示library名称。Lua代码require "xxx"需要与之对应。 38 //3. 在luaL_register的调用中,其第一个字符串参数为模块名"xxx",第二个参数为待注册函数的数组。 39 //4. 需要强调的是,所有需要用到"xxx"的代码,不论C还是Lua,都必须保持一致,这是Lua的约定, 40 //   否则将无法调用。 41 extern "C" __declspec(dllexport) 42 int luaopen_mytestlib(lua_State* L)  43 { 44     const char* libName = "mytestlib"; 45     luaL_register(L,libName,mylibs); 46     return 1; 47 }
复制代码

    见如下Lua代码:

1 require "mytestlib"  --指定包名称 2  3 --在调用时,必须是package.function 4 print(mytestlib.add(1.0,2.0)) 5 print(mytestlib.sub(20.1,19))

posted @ 2014-12-19 19:12 多彩人生 阅读(421) | 评论 (0)编辑 收藏

仅列出标题
共25页: 1 2 3 4 5 6 7 8 9 Last 

导航

统计

常用链接

留言簿(3)

随笔分类

随笔档案

搜索

最新评论

阅读排行榜

评论排行榜