
C
文章平均质量分 78
scott.cgi
要么编程,要么被编程,编程是一种超能力
展开
-
Android OpenSLES error “too many objects” 和 “Error after prepare: 1” 问题的解决方式
在使用NDK直接调用OpenSLES实现音频的时候,很容易出现以下两种错误:(1) E/libOpenSLES(25131): Too many objects(2) E/libOpenSLES: Error after prepare: 1第一个, 是SLPlayItf对象没有及时销毁,不同的平台SLPlayItf同时支持的数量不同,大约是2-10左右,所以音频播放完成之后,需要及时销毁...原创 2019-03-08 20:50:10 · 1334 阅读 · 0 评论 -
C 语言链式调用与Tween算法实现(4)链式封装接口
在有上下文this指针的语言中,可以把this指针return出去。这样就可以形成一种链式调用的效果。配合上良好的方法命名,能够让函数功能的组合调用,使用起来非常的直觉化。在C语言中并没有this指针,所有的上下文对象需要,手动传入上下文对象。以前的几篇文章介绍了3篇关于C语言如何实现tween缓动算法的。然而,函数的调用缺少链式调用非常的不流畅。而tween又很多默认参数的设定,往往链式调用能够原创 2016-12-07 21:52:36 · 880 阅读 · 0 评论 -
C 语言实现协程
C 语言实现协程,最困难的部分就是上下文信息的保存和还原。这样才能够做到,让协程在任意位置让出执行权限,稍后再恢复到中断位置继续执行。C 实现协程一般有几个方案。使用第三方库来保存恢复上下文数据,比如ucontext使用汇编来保存上下文信息使用setjmp / longjmp 保存恢复上下文信息使用switch case的特性来做上下文断点继续,上下文信息需要用static变量保存原创 2016-11-24 18:41:16 · 2484 阅读 · 0 评论 -
C 语言单例的一种实现
单例的核心就是要只维护一份对象结构在内存里。在面向对象语言里,可以使用private constructor来阻止产生对象拷贝,在使用static变量来持有唯一对象实例。在C中通常会使用方法体内的static local变量来持有对象实例。通过实践,这里给出一种更加简单直觉的构建方法。先看代码。struct ACamera{ float left; float right; float原创 2016-12-01 14:28:17 · 575 阅读 · 0 评论 -
矩阵旋转算法提高75%运算
矩阵旋转,有4种情况。绕X轴旋转绕Y轴旋转绕Z轴旋转绕任意轴旋转首先,给出通常的算法。typedef union{ float m[16]; struct { float m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15; };}原创 2016-08-22 22:49:46 · 1521 阅读 · 0 评论 -
C 语言通过结构体成员获得结构体指针
通过结构体成员拿到结构体的指针,是C语言实现继承多态的基础。面向对象C编程可以参看这里OOC 面向对象C语言编程实践。这里详细介绍这个核心的操作方法。/** * Get struct pointer from member pointer */#define StructFrom2(memberPtr, structType) \ ((structType*) ((char*) m原创 2016-08-31 20:50:03 · 4924 阅读 · 0 评论 -
OOC 面向对象C语言编程实践
面向对象是一种编程思想,虽然C并没有提供面向对象的语法糖,但仍然可以用面向对象的思维来抽象和使用。这里分享一套C面向对象的写法,可以完成面向对象编程并进行流畅的抽象。这套写法是在实践中不断调整的结果,目前已经比较稳定,进行了大量的功能编写。 这套OOC有以下特性:没有强行去模仿c++的语法设定,而是使用C的特性去面向对象设计实现继承,组合,封装,多态的特性一套命名规原创 2016-07-23 17:10:57 · 2484 阅读 · 3 评论 -
面向组件,状态机,消息驱动,三合一的编程模型
在实践中,发现面向组件,状态机,消息驱动。如果整合起来的模型,能够更为自然和简单的进行抽象。当然这些都是以面向对象为基础,更进一步的抽象扩展。本文,先会分别介绍一下,面向组件,状态机,消息驱动的各自特点。然后,介绍如何整合三者。最后,给出代码示例。第一,面向组件在游戏开发中有些引擎会使用基于组件的架构。比如unity3d就是其中的典型。基于组件,有以下特性。基类原创 2016-07-28 17:17:12 · 2480 阅读 · 1 评论 -
C 实现通用Tween缓动动画(3)快捷链式调用接口
Tween创建action有很多属性设置,不同的动画效果,需要不同的属性控制。多个action的动画需要多次设置,使用起来十分不方便,还要创建临时数组存放一组action。通常,tween的参数设置会使用链式调用,形成一组连续的控制。在面向对象中上下文可以获得当前对象,但在C中无法获得。往往在C中方法设置一个对象的属性,需要把当前对象手动传进去非常不方便。所以,我们需要构建一个上下文,保存链式调用原创 2016-07-06 15:32:11 · 964 阅读 · 0 评论 -
OpenGL坐标系和像素坐标系
OpenGL坐标系原点在中心,并且做了归一化处理。就是说xy轴,都是从[-1, 1]之间。而像素坐标系是同样的中心点,右上是正方向,只是没有做归一化处理,是以像素为单位的。那么,归一化的坐标系和像素坐标最大的区别就是在于,像素是实际的单位,会根据像素数值所变化。而归一化坐标是一个比例,只和屏幕的相对大小有关系。 比如,在同样屏幕尺寸,高分辨率会压缩像素坐标,低分辨率会放大像素坐标原创 2016-05-27 13:06:58 · 6277 阅读 · 0 评论 -
C99 goto label地址实现C语言协程
以前用C语言中的switch case实现过一个简单的协程,并应用到了实际的项目里。文章在这里,C语言实现协程,最近了解到C99中,goto语句可以跳转到一个变量里,变量保存的是label的地址。于是瞬间想到,这个可以替换协程实现中的switch case的机制。首先,说明一下什么是goto到标签地址。int main() { static void* p = &&labe原创 2017-04-12 09:53:03 · 2576 阅读 · 0 评论 -
C语言调用jni中JNIEnv指针使用和理解
使用C语言调用jni的时候,需要和java的环境对象和虚拟机对象交互。它们的C语言定义如下。typedef const struct JNINativeInterface* JNIEnv;typedef const struct JNIInvokeInterface* JavaVM;可以看到,JNIEnv和JavaVM是一个指针内心。其结构体包含了很多我们需要用的函数指针: j原创 2017-04-04 22:59:56 · 6616 阅读 · 0 评论 -
「游戏引擎Mojoc」(10)Android NDK通用JNI调用Java代码封装
Mojoc提供了一个通用的工具类,来调用Android Java代码,以实现特定平台的功能。这个工具类封装了JNI使用的繁琐细和上下文对象的获取,提供了简单直接的API专注于Java类和方法的访问,并且实现了任意类型Java方法的调用。本文将会介绍以下几点:NDK NativeActivity的JNI上下文对象获取。JNI中JNIEnv指针的使用和理解。根据路径获取Java类对象。...原创 2018-05-20 20:19:56 · 528 阅读 · 0 评论 -
「游戏引擎Mojoc」(9)C使用二分查找实现泛型字典映射
字典映射是最基础,最重要的数据结构,通常会利用哈希表来实现。Mojoc提供了另外一种形式的实现,通过数组和二分查找策略,来完成字典数据的映射。源代码在这里:ArrayStrMap.h。原理字典映射的核心在于,如何把一个字符串,通过某个策略映射到一个唯一的标识上。利用hash算法生成hash code,然后映射到数组index上就是一种方法。Mojoc ArrayStrMap的思路很简单原创 2018-01-05 17:59:23 · 612 阅读 · 0 评论 -
「游戏引擎Mojoc」(2)C代码风格
代码风格的问题,很微妙,也很有趣。因为它并不影响代码的运行和功能,但它连接着人的心灵和信仰。代码风格目的简单明确,就是增加代码的可阅读性,降低维护成本,减少心智负担。纠结的地方在于,每个人对“可阅读性”的理解和喜好不同。专注容易产生喜爱,喜爱容易滋生癖好,代码写的越多,越会形成个人风格习惯。而逻辑性,还容易在大脑中创造强迫症的倾向,所以代码风格会演变成信仰,难以动摇。因为代码风格不喜欢,很可能就会否原创 2017-10-23 10:27:04 · 869 阅读 · 0 评论 -
「游戏引擎Mojoc」(3)C面向对象编程
用C语言进行面向对象编程,有一本非常古老的书,Object-Oriented Programming With ANSI-C。1994出版的,很多OOC的思想可能都是源于这本书。但我觉得,没人会把书里的模型用到实际项目里,因为过于复杂了。没有必要搞出一套OOP的语法,把C模拟的和C++一样,那还不如直接使用C++。Mojoc使用了一套极度轻量级的OOC编程模型,在实践中很好的完成了OOP的抽象。有以原创 2017-10-23 10:29:39 · 1031 阅读 · 0 评论 -
「游戏引擎Mojoc」(7)C使用goto label地址实现协程
C 语言实现协程,最困难的部分就是上下文信息的保存和还原。这样才能够做到,让协程在任意位置让出执行权限,稍后再恢复到中断位置继续执行。C 实现协程一般有几个方案。使用第三方库来保存恢复上下文数据,比如ucontext。使用汇编来保存上下文信息。使用setjmp / longjmp 保存恢复上下文信息。使用switch case的特性来做上下文断点继续,上下文信息需要用static变量保存。比原创 2017-10-23 10:35:31 · 851 阅读 · 0 评论 -
「游戏引擎Mojoc」(8)C实现泛型ArrayList
泛型ArrayList是基础的数据结构,然而在C的标准库里并没有提供,所以需要自己手动实现一个。Mojoc的ArrayList实现经过了实践的测试,达到了稳定和高效的状态,源码ArrayList.h。本文主要介绍实现思路和一些特性,Mojoc的泛型ArrayList主要完成了以下几个功能:存取放任意数据类型。动态内存扩展。针对栈数据与堆数据不同的存储策略。一组简洁的数据操作接口。利用宏进行原创 2017-12-03 16:58:00 · 537 阅读 · 0 评论 -
C语言中获取整数和浮点数的符号位
1. 为什么要获得符号位很多时候,我们需要判断数值的正负,来做相应的逻辑处理。条件判断语句可以很好的完成这个需求。有时候会有下面的情况,if (x > 0) { x = x - 1;} else { x = 1 - x;}if (x < 0) { x = -x;}正负只是数值的符号位变化,或是计算结果的符号位变化。但是我们需要用一个判断,首先原创 2015-03-19 19:05:51 · 9090 阅读 · 1 评论 -
Quake3 快速开平方和开平方倒数计算优化
在Quake3中,卡马克使用了广为人知的魔数来优化,开平方和开平方倒数计算。而在Doom3中改为查表计算了。 [cpp] view plain copy /* ================ SquareRootFloat ================ */ float SquareRootFloat(floa原创 2016-02-23 08:46:47 · 3400 阅读 · 0 评论 -
C 实现通用Tween缓动动画(2)Tween数据结构
首先,tween动画需要能够完成以下几个功能。设定时间,目标值,插值公式,完成动画运动动画完成后调用回调函数可以在同一动画过程中,进行多个数值的同时插值计算动画可以进入队列顺序执行,也可以并发执行可以销毁指定动画 根据上述需求,我们需要以下数据结构。TweenActionValue,代表动画控制的一个属性数值原创 2016-07-05 20:53:06 · 1341 阅读 · 0 评论 -
C 实现通用Tween缓动动画(1)插值公式
Tween缓动动画在ui中大量的使用,根据缓动算法可以很快的创造出,预定的缓冲运动效果。其核心的概念就是,给出初始值,目标值,时间。然后差值之间每个时间点上的数值变化,从而得到一组运动轨迹。 我实现的Tween通用结构,主要分为3个部分,每个部分单独一篇文章来解释。第一, 插值算法公式。根据初始值,目标值,和当前时间,来计算当前属性值。第二, 定义Tween执行状原创 2016-07-05 14:18:20 · 3518 阅读 · 0 评论 -
realloc 使用和思考
realloc来自c语言的标准库,函数签名如下:extern void* realloc(void *, size_t);这个函数用于重新分配指针地址对应的内存空间。第一个参数,需要重新分配内存空间的指针。第二个,参数重新分配的内存空间大小。特别之处在于,realloc在增加内存的情况下,就是size_t大于原有指针内存空间大小,首先会试图去追加地址空间。比如:原创 2014-08-08 16:56:25 · 1258 阅读 · 0 评论 -
C 语言复杂声明的理解
C语言常常因为声明的语法问题而受到人们的批评,特别是涉及到函数指针的语法。C语言的语法力图使声明和使用相一致。对于简单的情况,C语言的做法是很有效的,但是,如果情况比较复杂,则容易让人混淆,原因在于,C语言的声明不能从左至右阅读,而且使用了太多的圆括号.但是找到正确的规则去理解, 无论多复杂都可以搞清楚.原则如下:1. 从里到外2.按照优先级顺序,优先级顺序相同时候,从右边原创 2014-08-09 10:12:39 · 851 阅读 · 0 评论 -
NDK 获得精确时间模拟System.nanoTime()
NDK 提供了POSIX:原创 2014-08-08 10:03:11 · 3613 阅读 · 0 评论 -
贝塞尔三次方曲线优化, 24次乘法转换成6次加法
贝塞尔三次方的公式,涉及到4个点。如p1,p2,p3,p4,其中p1是起点,p4是重点, p2,和p3是控制点。公式如下:原创 2014-08-08 09:37:43 · 2028 阅读 · 0 评论 -
C语言,模拟命名空间的方法
C语言中没有单独的命名空间的定义. 所以, 通常会把函数,结构体的名字命名的很长, 加上前缀, 依次来防止命名冲突. 通过一些探索,我发现通过C语言现有的语法, 是可以在一定层面上来模拟命名空间定义的.一目了然看代码:原创 2014-08-08 09:28:32 · 2310 阅读 · 0 评论 -
在NDK中使用libpng读取pixel数据
libpng的详细使用方法在于它的官方文档libpng-manual.txt,下载文件夹下含有。使用openGL生成纹理的时候需要图片的像素数据。使用libpng可以帮助我们解析PNG标准格式的结构,获得pixel数据。在NDK中读取assets文件夹内容的方法在头文件#include 中定义。直接看代码:/** * Read png pixel data from file,原创 2014-08-08 17:27:16 · 2162 阅读 · 0 评论 -
C 语言中的达夫设备 Duff’s Device
在495个必须知道的C语言问题这本书中,提到了一个达夫设备另类的算法设计技巧。如下:register n = (count + 7) / 8; /* count > 0 assumed */switch (count % 8){case 0: do { *to = *from++;case 7: *to = *from++;case 6: *to = *from++;case 5:原创 2014-08-08 10:56:18 · 2824 阅读 · 0 评论 -
C 语言泛型数组实现
typedef struct { // element byte size int stride; // element number int length; // memory data void* data;} Array;data是个指针,需要malloc申请动态内存。对,这里面放的是数组的数据。好的,那么现在数据有了,那原创 2014-08-08 15:39:40 · 1809 阅读 · 0 评论 -
C 语言计算精确时间
C 语言标准库包含了时间相关的API。但是所有的精确值都是秒为单位的。那如何精确到毫米或是更精准的计算时间差呢。有如下定义:#define CLOCKS_PER_SEC 1000000 extern clock_t clock(void);clock_t() 返回的是CPU的时钟数,而常量CLOCKS_PER_SEC表示一秒钟有多少个始终数。那么原创 2014-08-09 10:08:42 · 1305 阅读 · 0 评论 -
C语言复合字面量的使用
C99增加的特性,复合字面量(composite literal)。一旦熟悉并使用,便会体会到简洁强大的表达。所谓字面量就是固定数值的表示。数值和字符串类型都有字面量的表达。如:// 100, 1.23f, "literral" 都是字面量int x = 100;float y = 1.23f;char* s = "literral";可看到字面构建的同时就可以复制给变量原创 2015-06-29 18:01:59 · 8098 阅读 · 0 评论 -
NDK 使用 addr2line 定位 Fatal signal (SIGSEGV) 错误
使用NDK编写native code时候,真机常会出现crash的错误。然后logcat就是一片错误堆栈。I/DEBUG ( 2562): signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 40123d5cI/DEBUG ( 2562): backtrace:I/DEBUG ( 2562): #00 pc 0原创 2015-07-07 14:52:23 · 8300 阅读 · 0 评论 -
C 实现解析Json字符串
除了C的标准库之外,依赖两个数据结构的实现,C 实现ArrayMap字典映射 和 C 实现泛型ArrayList数组。实现了标准的json结构解析,并提供一套访问json数据对象属性的接口。 首先,看数据结构的定义。 typedef enum{ json_object, json_array, json_string, json_float, json_n原创 2016-07-15 17:32:19 · 2139 阅读 · 0 评论 -
C 实现ArrayMap字典映射
字典映射是最重要的基础工具。我并没有使用hash做散列映射,而是使用了简单直接的二分查找。其主要的思路如下:使用字符串的长度,进行二分查找存储如果字符长度相等,使用字符串的字典顺序,进行二分查找存储缓存字符串的长度,用来减少字符串长度的计算函数调用元素是有序的存储在一个动态数组里提供一套元素的访问方法实现依赖 C 实现泛型ArrayList数组 首先看结构 ty原创 2016-07-13 16:29:19 · 1861 阅读 · 0 评论 -
C 实现泛型ArrayList数组
ArrayList数组是基石,是完成更复杂功能的基础。几乎所有的语言所提供工具库中,都含有ArrayList数组结构,唯有C的标准库中没有提供。我的实现是工具箱的一部分,上层已经依赖完成诸多功能。所以,正确性和效率是经过验证的。 实现的核心是利用了标准库realloc的特性,实现之前我也参看过很多开源的代码和思路。使用realloc并非是最好的选择,但是最简单最容易想到的实现。可原创 2016-07-11 23:03:13 · 1448 阅读 · 0 评论 -
C 实现ArrayQueue队列
在自增数组的基础上实现的,依赖C 实现泛型ArrayList数组。完成以下功能:元素的入队出队容量控制移除指定位置元素 typedef struct{ ArrayList arrayList[1]; /** * ArrayQueue top element index */ int topIndex;}ArrayQueue;typed原创 2016-07-12 17:59:18 · 855 阅读 · 0 评论 -
C 语言泛型Array数组封装
以前,写过一个C 语言泛型数组实现,但在实际的使用过程中,发现了更加易用的模式,进行了改进。这个数组封装作为一个最基础的结构,在此之上实现了动态数组,队列,数组映射等。还利用这些数据结构实现了一个简单的json解析器,已经成为C工具箱的最基础工具,可以验证这些结构的可用性和稳定性,以后将逐步介绍。 这个泛型数组分为代码实现和宏定义两部分,主要完成以下功能。可存储任意原创 2016-07-10 20:45:36 · 1695 阅读 · 0 评论 -
NDK 编译armebai-v7a的非4字节对齐crash Fatal signal 7 (SIGSEGV) 错误解决
一直都是编译armabi的,没有任何问题,这个架构是软件模拟浮点运算的。后来看到NDK文档上说armabi-v7a是针对有硬件处理浮点计算的arm cpu的。于是就修改配置编译armebai-v7a的so文件。结果是编译没问题,一运行就是crash掉,Fatal signal 7 (SIGSEGV)错误。进过排查才发现,crash掉的仅仅是对一个浮点变量赋值而已。原创 2015-07-08 14:28:10 · 3038 阅读 · 0 评论 -
C 语言 switch case 优化和小技巧一发
有一种使用switch case 的情况,就是更具不同的枚举常量,去case设置一个对象不同的属性值。比如:struct A { int p1; int p2; int p3;} a;enum { one, two, three,}switch(n) { case one: a.p1 = 10; bre原创 2015-08-13 22:51:23 · 3695 阅读 · 0 评论