Category Archives: Software Development

关于编程语言的选择与体会

从我最早接触编程至今已有近10年时间,当时是在初中时,通过文曲星编写了几款基于文字和简单图形的游戏。高中时因没有相关条件与指导,慢慢就荒废了下来,中途曾经因为计算机考试学过一段时间VB,但就当时的知识能力,并没有学习的很深入。上大学以后,学校开设了C语言和VB的相关课程,加之之后对单片机和嵌入式系统的狂热,让我更加深入的接触了计算机编程的原则与方法。

我虽然不是计算机专业出生,但在学习、工作中还是经常会接触到程序编程。我主要使用的依然是C语言,但是因为涉猎较广,还是接触了很多其他的编程语言。这里,我想把所有使用过的编程语言的优缺点罗列、整理一下,作为一次回顾。

BASIC:较为古老的编程语言,开发环境是基于命令行的,条件、跳转很不方便,现在已经很难见到。

VB:可视化BASIC,在BASIC上作了大量拓展,可以快速构建一个图形用户界面,但是能实现的功能比较简单。在工控上经常能见到,老工程师都会。

C:C语言作为基础性语言,广泛用于单片机与Linux编程中,其直接操作内存和硬件的特性,使其非常适合编写系统底层程序。C语言可以很好的完成单一任务,如一个算法的验证,但无法完成框架复杂性高、以及需要图形界面的场合。

C++:面向对象,结构化的语言,相比C语言可以实现更加清晰的程序框架。一般使用Visual C++作为开发环境,配合MFC程序框架可以实现功能复杂、通用性好的Windows程序。网上很多源代码都是基于VC的,但是其开发效率有点低下,并且实现复杂的图形界面比较困难。

C#:新一代的编程语言,结合了C++的面向对象以及VB的可视化开发的优点,又可以说是一种类JAVA语言。C#的开发效率高,图形绘制,数据库的功能强大,但目前对我来说的阻碍是很多开源软件对其的支持还不够,就如Win7一样兼容性还不够,随着时间的推移这个矛盾应该会逐步化解,我也准备逐步由C++转向C#开发。

Java:我接触Java并不多,初步感觉其对象化实现的很好。Java之所以生命力顽强,是因为其基于虚拟机的特性。虽然这降低了系统的运行效率,但是却实现了跨平台支持。目前由于Android开发的火热,很多人都在从事Java开发,我最近也有打算了解一下Android开发,届时也可以更深入的了解Java语言。

Lua:强大的脚本语言,初步体验了一下,感觉其扩展性、灵活性非常好,但是脚本语言与一般编程语言在设计思路上有一些不同,对我来说有一些难用。

Shell:Linux下的脚本语言,可以实现BATCH批量操作,甚至很多复杂的程序也可以通过Shell实现。

Matlab:擅长矩阵运算,建模能力强大,主要实现算法验证。但不适合用于设计大型程序,与一些上位机有接口,其作为一个组件使用可能更合适。

Python (修订于: 2017-05-12):目前最主流的科学计算脚本语言。相对MATLAB,Python有强大的开源社区支持,通过NumPy + SciPy + Matplotlib可以实现近似Matlab的科学运算编程。而DeepLearning的相关库 (TensorFlow, Theano, Keras) 也都有Python的对应版本。

当Printf遇到多线程

====================================================================

我注意到有很多人通过关键字”printf 多线程”搜索到了我的这篇文章,我也意识到有很多Linux和Windows程序员在编写多线程程序中使用printf导致的种种问题。我猜测这与printf设计时的不可重入性有关,虽然我在文中用嵌入式的串口打印函数作为类比,可是这两个或许还不是一回事。
如果你遇到了这个问题,你可以尝试以下方法,即使用多线程运行时库(Mulit-Thread Runtime Library):

1、VC环境
Project-> Settings-> C/C++-> Code   Generation-> use   run-time   library
如果希望在多线程中使用,那么要选择multithreaded dll
当然如果你只是作为调试,可以使用TRACE宏。

2、Linux环境
Linux环境中如何设置运行时库的参数我不是非常清楚,不过只要保证调用的是多线程运行时库即可。可是,Linux会有这个问题么?

3、更通用的方法
更通用的办法就是使用互斥锁、信号量等方法,不过这可能会改变程序运行的本意。

 

以下才是原文的正文,不过如果你只是来解决以上问题的,本文就对你没有价值了:

====================================================================

本文作者:云飞工作室(YunFei Studio),戴晓天

联系方式:Automatic.dai@gmail.com

原文地址:www.YFworld.com


一、本文背景

Printf()这个函数我想大家再熟悉不过了,可是对于如何在多线程中使用Printf(),各位可能就没怎么接触过了。本文以VC6.0为开发平台,旨在利用多线程完成一个最简单的任务:在屏幕上一直输出”Hello,world!”。
因为个人水平有限,本文涉及的内容非常肤浅,不过我还是尽量将原理讲清楚,希望对初学者略有帮助。

为了提高大家的兴趣、降低理解难度,文章的结构也是几经修改。考虑到本文阅读者可能对于多线程不怎
么了解,本文将首先介绍Win32多线程编程。

二、多线程概述

2.1 进程与线程

在操作系统中,一个进程就是一个程序的实例。当你双击打开一个程序之后,实际上就启动了一个进程。该进程将程序代码装载至RAM,并运行、管理该实例。而线程是进程的最小分割,好比运行一个盖楼房的程序进程,需要各有分工,有的人打地基,有的人刷水泥,有的人搬材料一样。这里,每一个人都是一个线程。相比单线程(一个人盖楼房),多线程(几个人配合盖楼房)可以显著提高系统运行的效率。线程彼此独立工作,却有相关性,比如打地基的要等搬材料的把材料运过来,才可以施工。这就说明,线程之间有时需要彼此配合完成任务,这就需要进程间通讯(IPC)。

2.2 Windows多线程编程

在Windows下使用多线程,实际上就是通过调用Windows提供的应用程序接口API来完成特定任务。其中,最基本的是创建一个多线程,该函数的原型为:

HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES lpThreadAttributes,  // pointer to security attributes
  DWORD dwStackSize,                         // initial thread stack size
  LPTHREAD_START_ROUTINE lpStartAddress,     // pointer to thread function
  LPVOID lpParameter,                        // argument for new thread
  DWORD dwCreationFlags,                     // creation flags
  LPDWORD lpThreadId                         // pointer to receive thread ID
);

Read more »

字节序:大端与小端

本文作者:云飞工作室,戴晓天

原文地址:www.yfworld.com

联系方式:Automatic.dai@gmail.com

本文背景:

对于嵌入式工程师来说,不仅要熟悉各种数据类型,还需要熟谙各种数据在内存中的表达形式。软件高手们通过内存与指针微妙的配合,总能摩擦出惊艳的火花。在讨论数据的存储结构时,必然会涉及到大端模式(Big-Endian)和小端模式(Little-Endian)的问题。平时编程时对于这个概念并不会有太多接触,但是在通讯协议的处理、可移植性方面就必须要考虑到字节序的问题。以下就来讨论这个问题。

一、大端和小端的起源

关于大端小端名词的由来,有一个有趣的故事,来自于Jonathan Swift的《格利佛游记》:

Lilliput和Blefuscu这两个强国在过去的36个月中一直在苦战。战争的原因:大家都知道,吃鸡蛋的时候,原始的方法是打破鸡蛋较大的一端,可以那时的皇帝的祖父由于小时侯吃鸡蛋,按这种方法把手指弄破了,因此他的父亲,就下令,命令所有的子民吃鸡蛋的时候,必须先打破鸡蛋较小的一端,违令者重罚。然后老百姓对此法令极为反感,期间发生了多次叛乱,其中一个皇帝因此送命,另一个丢了王位,产生叛乱的原因就是另一个国家Blefuscu的国王大臣煽动起来的,叛乱平息后,就逃到这个帝国避难。据估计,先后几次有11000余人情愿死也不肯去打破鸡蛋较小的端吃鸡蛋。这个其实讽刺当时英国和法国之间持续的冲突。Danny Cohen一位网络协议的开创者,第一次使用这两个术语指代字节顺序,后来就被大家广泛接受。

二、什么是大端和小端

Big-Endian和Little-Endian的定义如下:
1) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
2) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。

举一个例子,比如数字0x12 34 56 78在内存中的表示形式为:

1)大端模式:

低地址 ————————> 高地址

0x12 | 0x34 | 0x56 | 0x78

2)小端模式:

低地址 ————————-> 高地址

0x78 | 0x56 | 0x34 | 0x12

可见,大端模式和字符串的存储模式类似。

大端小端没有谁优谁劣,各自优势便是对方劣势:

大端:容易判断正负(offset(0));

小端:易于进行数据类型转换,1、2、4字节的存储方式一样。

三、如何判断机器的字节序

可以编写一个小的测试程序来判断机器的字节序:

BOOL IsBigEndian()
{
	int a = 0x1234;
	char b =  *(char *)&a;	// 取b等于a的低地址部分
if( b == 0x12)
{
	return TRUE;
}
return FALSE;
}

网上还有一种使用联合体的方法:

BOOL IsBigEndian()
{
	union NUM
{
	int a;
	char b;
}num;
num.a = 0x1234;
if( num.b == 0x12 )
{
	return TRUE;
}
return FALSE;
}

Read more »

SQLite BLOB的使用、出现乱码问题并解决

 (*)本文系本博客原创,如需转载请注明原作者!

原文作者:戴晓天,云飞实验室

联系方式:automatic.dai@gmail.com

原文来自:www.yfworld.com

SQLite是轻量级数据库,但其功能齐全,当然也包括了对BLOB对象的操作功能。但今天在做SQLite的BLOB功能测试时,出现了读取出的数据与写入数据不一致的情况,这让我十分费解。

测试程序将一幅图片文件读入内存,写入数据库。之后从数据库中读出,再写出成图片文件。整个程序的执行过程示意如下:

1. 打开数据库

sqlite3_open("blob.db",&db);

 

2. 新建一个表,包含两个字段:name和item,其中name为varchar(128)是文件名,item为blob类型

sprintf( sql,"CREATE TABLE blob(id varchar(128) UNIQUE,item BLOB)" );
sqlite3_exec(db, sql, 0, 0, &zErrMsg);     // zErrMsg是错误代码

 

3. 准备一次blob传输,其中 ? 为占位符,之后要将其绑定

(*)stat为sqlite_stmt * 类型

sqlite3_prepare(db, "INSERT INTO blob values (1,?);", -1, &stat, 0);

 

4. 打开一个对象,以便将其绑定

(*)数据保存在pFile中,数据大小保存在filesize中,在下一步会用到。

fp = fopen("test.bmp", "rb");

//首先计算文件大小
fseek(fp, 0, SEEK_END);
filesize = ftell(fp);

fseek(fp, 0, SEEK_SET);

//将数据读入到缓冲区
pFile = new char[filesize];
size_t sz = fread(pFile, sizeof(char), filesize, fp);
fclose(fp);

 

5. 绑定数据并执行

sqlite3_bind_blob(stat, 1, pFile, filesize, NULL);
sqlite3_step(stat);
sqlite3_finalize(stat);  // Release sqlite_stmt

—————————————————————-

以上完成了blob数据的写入,现在将其读出。

6. 进行一次读出操作

sqlite3_prepare(db, "select * from blob;", -1, &stat, 0);
sqlite3_step(stat);

 

7. 得到Blob文件的指针和大小

const void *pBlob = sqlite3_column_blob(stat, 1); // Get blob,1为列号
int blob_size = sqlite3_column_bytes(stat, 1);    // Get size

 

8. 将其写入文件

fp = fopen("test_output.bmp", "w+");

size_t sz = fwrite(pBlob, sizeof(char), blob_size, fp);

 

至此,一个Blob对象的写入/读出操作就完成了。

—————————————————————-

Read more »