设计开发

CentOS 7下编译FBX SDK示例时的”cannot find -luuid”问题

在Linux环境下尝试编译FBX SDK中的samples时,最后链接时出现”cannot find -luuid”,查了下文档发现这个uuid库是linux下生成唯一id用的那么一个库,起初以为是少了什么lib或者devel之类的,于是用yum开始安装,结果libuuid、uuid-devel都装上了还是不行,于是又都逐一卸载掉,查看ld的search path,在/lib64/下找到了:

lrwxrwxrwx. 1 root root 16 4月 7 22:35 /lib64/libuuid.so.1 -> libuuid.so.1.3.0
-rwxr-xr-x. 1 root root 20032 4月 1 01:37 /lib64/libuuid.so.1.3.0

用yum确认了下,也确实是已安装有这个uuid相关的库以及include等,于是怀疑是符号链接的问题,试了下用

ln -s libuuid.so.1 libuuid.so

建立libuuid.so的符号链接,重新make,成功通过并生成了sample的执行文件。

PS: FBX SDK的sample中的MakeFile将CC和LD设置成了gcc4,这个在我的CentOS7下会找不到(默认安装的应该都是),于是直接删掉了4。

对于Android NDK编译器ARM和Thumb模式的理解及Toolchain的切换clang编译器

以前在做Symbian的时候,曾经研究过ARM CPU的指令集问题,ARM处理器支持两套指令集,即ARM和Thumb。ARM为32位指令集而Thumb为16位指令集,理论上32位可以提供更快的执行速度但会生成更大的二进制执行文件,而16位的Thumb则恰恰相反,省地儿但慢,这也正是体现出了ARM对于嵌入式设备的专业性。对于我这种牺牲一切换速度的理念来说,当时就留下了ARM就比Thumb快的印象,以致于现在在做Android NDK原生开发时,也是优先用ARM指令集。(这个可以通过在Android.mk中加入LOCAL_ARM_MODE := arm控制,默认情况下NDK使用Thumb指令集)

但是最近在Xcode编译iOS项目时,注意到同为ARM处理器的苹果设备,使用的是Thumb指令集,而且好像还是某种新版本的Thumb指令集,小搜索了一下看到有人说这种armv7引入的叫做Thumb-2的指令集要比arm指令集更好!于是又重新搜索更新了一下大脑知识库…

Continue reading…

对Unity3D的iOS导出插件XUPorter的plist处理功能的改进

XUPorter

是一个可以在U3D生成iOS所需Xcode项目时自动完成一些如添加framework,修改编译参数等操作的Editor插件。这个插件对于同一个项目需要接入各种不同渠道的SDK生成对应IPA的需求可以很方便快捷的实现自动化操作,降低项目维护复杂度。
在使用这个插件时,发现了些小问题,查看作者声明时发现其已经不在对这个插件进行维护了,于是只好自己动手做一些修改完善:
本文记录的就是对plist的处理功能,原代码逻辑中XCProject.cs中的ApplyMod函数会根据.projmods的信息对Xcode项目文件进行一系列的修改,其中一部是对项目.plist的修改,但这一步用我当时取到的github最新版本时会出错,仔细检查了下,发现无论projmods中的plist段写不写,生成对应的XCMod对象的plist总会是null,检查了下这个json数据解析生成类,发现plist的类型是“Hashtable”,而不像其他一些字段,如group是string,libs是ArrayList等,改换了下projmods中的json写法,又发现虽然可以解析成功不为null了,但实际修改plist逻辑又出现了问题,原逻辑是通过XCPlist的Process函数对projmods中提供的信息项对原项目plist进行合并修改,但是代码中对各种plist选项的处理不并完善,只有一个特殊if:

		public void AddPlistItems(string key, object value, Dictionary<string, object> dict)
		{
			Debug.Log ("AddPlistItems: key=" + key);
			
			if (key.CompareTo(PlistUrlType) == 0)
			{
				processUrlTypes((ArrayList)value, dict);
			}
			else
			{
				dict[key] = HashtableToDictionary<string, object>((Hashtable)value);
				plistModified = true;
			}
		}

会对URLSchemes做处理,显然这样无法实现通用的plist修改逻辑,思考过后我决定将其实现改为读取指定plist文件中的key项并与项目plist进行合并,覆盖已有的项,添加没有的项,具体实现如下:
Continue reading…

Unity3D中LoadLevelAsync异步加载场景的延迟切换问题

Unity中,对于异步加载场景的方式,脚本文档中有一定的解释和示例代码:http://docs.unity3d.com/ScriptReference/Application.LoadLevelAsync.html
其默认情况下,会在异步加载完成后立即切换到目标场景,但有些时候,需要在切换完成时先做一些操作,比如更新UI显示,释放资源等,也就是延迟切换场景的时间,这时就需要用到LoadLevelAsync返回值AsyncOperation的allowSceneActivation属性,将其置为false后,就不会立即切换场景了,但是有一个小问题就是,引擎底层对于这个逻辑的处理会变为,场景加载完成后,AsyncOperation的isDone以及progress都不会是正常的完成标记,也就是true和1.0,而是false和0.9,所以在需要手动置allowSceneActivation为true切换场景的位置的加载完成逻辑判断方式也需要调整为progress的0.9了。

Unity3D使用MonoDevelop进行开发时的项目编译问题

自从VS2015出现以后,Unity3D的新版本也直接内置了对其支持,写代码和调试都非常方便,但是在没有VS2015的开发环境下,比如没装或者是装不了(Mac OSX)下,用Unity自带的MonoDevelop也还算方便。
这次记录的是一个之前太注意的小问题,C#脚本中写了个带默认参数的函数,结果发现Unity编辑器可以编译运行,但在MonoDevelop调试时却提示编译错误,检查了下,发现原来是默认用MonoDevelop调试时,这个IDE也会对打开的项目进行编译,但其编译的方式和Unity本身不太一样,对这些后加入支持的代码写法并不支持,解决方法也很简单:Tools->Options->Unity->Debugger->Build project in MonoDevelop,这个选项勾掉就可以了。

OpenWRT下libv4l的编译问题(uClibc++、stdc++相关)

最近研究路由器上的摄像头监控,要用到libv4l2的库,结果用OpenWRT SDK编译时却遇到了问题,路由器cpu是MT7620A,用的SDK是OpenWrt-SDK-ramips-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2,用./scripts/feeds安装了libv4l后,直接make报错:

In file included from v4l2-compliance.cpp:37:0:
v4l2-compliance.h:25:18: fatal error: cerrno: No such file or directory
 #include <cerrno>

看了下,是c++写法下的errno头文件找不到,V=s看了详细日志,-I的头文件搜索路径里确实没有cerrno,但是这个文件确实存在于这里:staging_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/usr/include/uClibc++/,也就是说-I少了个带uClibc++的路径,看了半天sdk里的各种.mk,也没找到什么配置参数方面的玄机,可又不想傻加上个-I,或者都改成errno.h,于是开始搜索…
Continue reading…

Android应用图标修改后真机显示不更新的问题及mipmap图标

问题大致就如标题描述的那样,应用图标修改后重新打包安装到设备上时并没有变化,当然,前提是已经排除了人为因素导致的res内图标文件替错等原因。许久以前,在Android的原始时期,1.6、2.2时代时,就曾经在HTC的Sense UI上遇到过类似问题,当时也没太在意,现在在OnePlus One上(CM12s系统)又遇到了同样的问题,决定彻查一下原因。
百度下发现MIUI等也有类似的问题,基本确定是Launcher对应用图标建立了缓存,最直接的破除缓存的方法就是修改应用的Package Name,换包名后重装图标就会显示正确,明显就是没有缓存的特征!然而,应用发布过后一般是不会更换包名的,所以这个方法实际应用意义不大,仅仅是确认了这个图标缓存的机制。
这之后又查到了一些解决方法,如删除 /data/system/customized_icons 路径下的响应图标(这个需要root,且在5.0上没有这个路径,估计是Pre Lollipop用的),再如杀掉Launcher的进程,强制其重启刷新缓存(这个貌似不科学,因为重启Launcher的话应该和重启系统性质是一样的,但是我试过重启机器后图标依然没有刷新,再有就是CM上也没找到明显的Launcher进程,只有个systemui看起来比较像,不过也不敢强制结束,怕玩坏啊,哈哈!),这之后又自己尝试了下别的可能作为缓存key的要素,如改VersionCode,改VersionName,同时改VersionCode和VersionName,改res下的图标文件名等,均无效!
Continue reading…

iOS Android平台下的wchar_t默认size问题

很久以前曾经被wchar的问题在iOS和Android上被坑过,这次是在参研一份有年头的代码时又遇到了宽字符的问题,当然,也是和wchar有关系的,就是这个wchar在各个系统平台下的sizeof问题,关键的是一段UTF-8转UTF-16的代码:

size_t Utf8ToUtf16(const char* src_, wchar_t* dest_, size_t destlen_, size_t srclen_ /*= 0*/) 
{
	if (srclen_ == 0)
		srclen_ = _utf_length(src_);
	size_t destcapacity = destlen_;
	for (size_t idx = 0; ((idx < srclen_) && (destcapacity > 0));)
	{
		wchar_t	cp;
		unsigned char	cu = src_[idx++];
		if (cu < 0x80)
			cp = (wchar_t)(cu);
		else if (cu < 0xE0)
		{
			cp = ((cu & 0x1F) << 6);
			cp |= (src_[idx++] & 0x3F);
		}
		else if (cu < 0xF0)
		{
			cp = ((cu & 0x0F) << 12);
			cp |= ((src_[idx++] & 0x3F) << 6);
			cp |= (src_[idx++] & 0x3F);
		}
		else
		{
			cp = L'?';
		}
		*dest_++ = cp;
		--destcapacity;
	}
	return destlen_ - destcapacity;
}

这段代码在win下可以正常将utf-8的char*转换为utf-16的char*,但在Android, iOS下却不能得到和win下一样的转换结果,刚发现这个问题时,以为又是当年遇到的wchar坑,宽字符函数不支持之类的,但是仔细看了下并没有用到什么字符串函数,转换部分也是自己实现的,最后在各平台调试器的帮助下找到了问题:
Continue reading…

Cocos2d-X lua binding C++类的RTTI

在用Cococs2d-X的lua binding时,遇到了需要RTTI的时候,也就是运行时类型识别,这点对于lua类来说还是很容易做到的,可以参考引擎lua framework中cocos/cocos2d/functions.lua中的function iskindof(obj, classname),不过,这个函数的递归实现函数iskindof_有些小问题,这里是修正方法:

local iskindof_
iskindof_ = function(cls, name)
    local __index = rawget(cls, "__index")
    if type(__index) == "table" and rawget(__index, "__cname") == name then return true end
    
    if rawget(cls, "__cname") == name then return true end
    -- By K-Res: should use __index instead of cls!
--    local __supers = rawget(cls, "__supers")
    local __supers = rawget(__index, "__supers") 
    if not __supers then return false end
    for _, super in ipairs(__supers) do
        if iskindof_(super, name) then return true end
    end
    return false
end

然而,当遇到需要对binding到lua的native class进行RTTI就有些麻烦了,可以看到借助tolua过去的lua对象是usertable挂metatable实现的,而metatable中也没有可以用lua类(确切的说是模拟class行为的table)的RTTI方式,因为需要查找的一些__cname等meta成员并不存在,作为class标识的只有一个.isclass的bool值,看了下binding实现的原生代码,发现在不添加额外元表信息的前提下获取class名称是需要用到LUA_REGISTRYINDEX这个只能由原生代码获取到的lua全局信息注册表,于是放弃了通过lua代码实现绑定类类型识别的想法,转而使用原生函数实现了个简单的获取binding时设置的本类class名方法,暂时实现了本对象所属类识别的功能:
Continue reading…

64bit Linux CentOS 7下编译32bit程序的方法

本文记录的方法理论上适用于所有RedHat系Linux发行版!
一般在64位Linux下(安装好gcc等相关编译工具后)编译出的执行程序都是针对64位环境的,如果想编译为针对32位环境的(当然,64位系统环境下也可以兼容运行),只需要在执行gcc时加上-m32编译即可(ld的话也有对应参数-melf_i386),虽然编译时只是加参数即可,但仍然有c、c++标准库等需要首先安装好32位相关版本。
如下,如果直接-m32编译的话,会收到如下错误提示:

[kres@localhost test6432]$ gcc -m32 test.c
In file included from /usr/include/features.h:399:0,
from /usr/include/unistd.h:25,
from /usr/include/usb.h:28,
from test.c:1:
/usr/include/gnu/stubs.h:7:27: 致命错误:gnu/stubs-32.h:没有那个文件或目录
# include ;
^
编译中断。

Continue reading…