摘要: 做移动开发快一年了,有幸接触了WM、Symbian、Android、iPhone等多个平台的开发。往往一个软件需要实现多个平台的版本,对于不同平台进行重新编码是一件很费劲的事情,其实我们可以通过代码共用技术,实现对一些代码的重用。 这一技术的应用,可以带来不少的好处:1.代码重用:节约开发和维护的时间2.核心代码的保护:将核心代码编译成库,只将库而不是源代码提供给上层开发人员使用。3.。。。。。。 本文将实现一个支持这几个平台的天气信息查询软件,软件采用C语言去实现调用WebService接口获取天气信息的功能,并将其编译成各种平台能够调用的库,而UI则采用各个平台各自的语言去实现,最终实现.阅读全文
posted @ 2011-05-21 14:39 luzj 阅读(2770) 评论(14) 编辑

     做移动开发快一年了,有幸接触了WMSymbianAndroidiPhone等多个平台的开发。往往一个软件需要实现多个平台的版本,对于不同平台进行重新编码是一件很费劲的事情,其实我们可以通过代码共用技术,实现对一些代码的重用。

      这一技术的应用,可以带来不少的好处:

1.代码重用:节约开发和维护的时间

2.核心代码的保护:将核心代码编译成库,只将库而不是源代码提供给上层开发人员使用。

3.。。。。。。

      本文将实现一个支持这几个平台的天气信息查询软件,软件采用C语言去实现调用WebService接口获取天气信息的功能,并将其编译成各种平台能够调用的库,而UI则采用各个平台各自的语言去实现,最终实现底层代码的共用。

先来看看最终的效果图:

一、底层代码的实现

我们要调用到WebService接口,需要使用网络

而对于不同的平台socket的使用上有细微差异,我通过条件编译的方式,实现对不同平台的兼容。

下面是实现代码:

//对于VC的DLL,需要导出函数,而其他的则不需要
头文件Common.h
#ifdef _MSC_VER
#define DLLFLAG _declspec(dllexport)
#else
#define DLLFLAG ""
#endif
//通过WebService接口获取天气信息
DLLFLAG char* getWeather(const char *cityName);
源文件Common.c
#include
<string.h>
#include
<Common.h>
#include
<stdlib.h>
//根据系统加载不同的网络库
#ifdef _MSC_VER
#include
<winsock2.h>
#pragma comment(lib, "winsock.lib")
#else
#include
<sys/socket.h>
#include
<netinet/in.h>
#include
<arpa/inet.h>
#include
<netdb.h>
#endif
#define BUFSIZ 4096
DLLFLAG
char* getWeather(const char *pCityName)
{
//对于VC需要初始化socket版本
#ifdef _MSC_VER
WSADATA wsaData;
int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
#endif
int sockfd = 0;
struct sockaddr_in addr;
char text[BUFSIZ] = "";
char header[BUFSIZ] = "";
char *content = (char*)malloc(BUFSIZ);
sockfd
= socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family
= AF_INET;
//不同平台填充地址字段的方式不同
#ifdef _MSC_VER
addr.sin_addr.S_un.S_addr
=inet_addr("222.73.218.218");
#else
inet_aton(
"222.73.218.218",&addr.sin_addr);
#endif
addr.sin_port
= htons(80);
memset(header,
0, sizeof(header));
strcat(header,
"GET /Service.asmx/getWeatherbyCityName?theCityName=");
strcat(header, pCityName);
strcat(header,
"&theDayFlag=Today HTTP/1.1rn");
strcat(header,
"Host: www.ayandy.comrnrn");
connect(sockfd,(
struct sockaddr *)&addr,sizeof(struct sockaddr_in));
send(sockfd, header, strlen(header),
0);
memset(text,
0, BUFSIZ);
memset(content,
0, BUFSIZ);
recv(sockfd, text, BUFSIZ,
0);
strcat(content, text);
//while ( recv(sockfd, text, BUFSIZ, 0) > 0)
//{
// strcat(content, text);
// memset(text, 0, BUFSIZ);
//}
//不同平台关闭socket的方法不同
#ifdef _MSC_VER
closesocket(sockfd);
WSACleanup();
#else
shutdown(sockfd, SHUT_RDWR);
#endif
return content;
}






二、Windows Mobile 平台

对于WM平台,为了与底层库相区别,我们就不用VC去实现UI,而使用C#来实现UI

1.编译dll

Visual C++  – 智能设备 – 由于没有好的dll模板,我们就建一个“MFC智能设备DLL”

取名ShareLib,然后在生成的项目中删除掉没用的文件(比如预编译啥的),添加我们的底层代码文件Common.h和 Common.c,最终文件结构如图:

然后编译,最终会生成ShareLib.dll文件

2.实现主界面

新建一个C#的智能设备项目,取名ShareLibTest


Form1.cs文件中,添加对于dll的引用

[DllImport(@"ShareLib.dll",CharSet=CharSet.Unicode) ]
public static extern IntPtr getWeather(string cityName);


然后进行界面的设计,最终界面如图:

然后给按钮设置点击事件:

try
{
    byte[] paraByte = Encoding.UTF8.GetBytes(txtLocation.Text);
 IntPtr p = getWeather(Encoding.Unicode.GetString(paraByte, 0, paraByte.Length));
 string newWeather = Marshal.PtrToStringUni(p);
 byte[] strByte = Encoding.Unicode.GetBytes(newWeather);
 newWeather = Encoding.UTF8.GetString(strByte, 0, strByte.Length);
 int a = newWeather.IndexOf("/>");
 int b = newWeather.IndexOf("http://");
    int aLength = "/>".Length;
    newWeather = newWeather.Substring(a + aLength, b - a - aLength);
 newWeather = newWeather.Replace("", "").Replace("", "");
    txtWeatherInfo.Text = newWeather;
}
catch (System.Exception )
{
}

代码中关键的一句就是使用Marshal完成从cchar* 转换为C#string,还有,需要注意字符的编码,否则可能会导致获取的数据乱码。

最终,运行程序就能看到效果了。

三、Android平台

1.编译so

对于Android平台,我们用Java实现UI

java中,要调用C/C++,需要使用jni技术

我们先写一个javaJniTest.java

代码如下:

public class JniTest {
    public native String getWeather(String cityNmae);
}

然后打开命令提示符:

//输入:
javac JniTest.java
//然后输入:
javah -jni com.luzj.ShareLibTest.JniTest

最终就会产生com_luzj_ShareLibTest_JniTest.h 文件,复制一份,将后者改为.c

打开com_luzj_ShareLibTest_JniTest.c文件,通过#include ”Common.h” 引入底层代码

然后去实现那个getWeather函数,在这个函数中主要完成对javaStringCchar*的相互转换工作,代码如下:

const char* name = (*env)->GetStringUTFChars(env, cityName, 0); 
const char *cWeatherInfo = getWeather( name );
jstring weatherInfo = (*env)->NewStringUTF(env, cWeatherInfo);
(*env)->ReleaseStringUTFChars(env,cityName,name);  
return weatherInfo;


然后编写一个make文件Android.mk,代码如下:

LOCAL_PATH:= http://www.cnblogs.com/lib
include $(CLEAR_VARS)
LOCAL_MODULE    := JniTest
LOCAL_SRC_FILES := com_luzj_ShareLibTest_JniTest.c Common.c
include $(BUILD_SHARED_LIBRARY)


最后,使用NDK-build一下,就会生成Android可用的动态链接库.so文件了

2.实现主界面

没啥好说的,对于开发过Android的人都能做到

然后在Activity中通过代码加载动态链接库

//加载c库
static {
System.loadLibrary(
"JniTest");
}

最后在要获取天气数据的地方调用JniTest类的中的getWeather方法即可


四、iPhone平台

iPhone平台,对于UI,使用Obj-C来实现。

iPhone平台上,我们可以将公用代码编译成静态库然后给程序调用。

1.编译静态库

首先,通过“Cocoa Touch Static Library”创建一个静态库的工程

将我们的底层库添加上去,编译一下,就会生成一个以“.a”为后缀的静态库了

2.实现主界面

拉个按钮到界面上去,给它添加事件

主要代码就下面两行,完成了NSString 与 char* 的相互转化,并调用了接口


char* strWeatherInfo = getWeather([txtLocation.text UTF8String]);
NSString
*weatherInfo = [NSString stringWithUTF8String:strWeatherInfo];

最后将数据显示到界面上即可

五、Symbian平台

我始终对这个平台没啥好感,况且这个平台的开发本身就是使用CC++,实现代码共用很容易的,在此我就不浪费笔墨了,有兴趣的自己试试。


六、总结

这一技术还是很有使用前景的,比如游戏开发者,可用通过代码共用,用Open GL 实现一个底层的游戏引擎给各个平台使用。

由于时间的关系,代码中对于异常的处理和一些条件的判断都没有去做,有兴趣的同学自己完善!

文章中的Demo已经打包,需要的可以自行下载。

下载地址:http://u.115.com/file/dn69hko2

在我的独立博客还有一些好文章,有兴趣的可以去看看:http://luzj.me/share-lib-test-mobil.html


作者:Luzj (luzjcn[at]gmail.com)
出处:http://luzj.me/share-lib-test-mobil.html
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

posted @ 2011-05-21 14:39 luzj 阅读(2770) 评论(14) 编辑

下面的六个程序片段主要完成这些事情:

文章来源于我的博客:http://luzj.me/

1. 输出Hello, World
2. 混乱C语言的源代码

下面的所有程序都可以在GCC下编译通过,只有最后一个需要动用C++的编译器g++才能
编程通过。

hello1.c

#define _________ }
#define ________ putchar
#define _______ main
#define _(a) ________(a);
#define ______ _______(){
#define __ ______ _(0x48)_(0x65)_(0x6C)_(0x6C)
#define ___ _(0x6F)_(0x2C)_(0x20)_(0x77)_(0x6F)
#define ____ _(0x72)_(0x6C)_(0x64)_(0x21)
#define _____ __ ___ ____ _________
#include <stdio.h>
_____

hello2.c 

#include <stdio.h>
main(){
int x=0,y[14],*z=&y;*(z++)=0x48;*(z++)=y[x++]+0x1D;
*(z++)=y[x++]+0x07;*(z++)=y[x++]+0x00;*(z++)=y[x++]+0x03;
*(z++)=y[x++]-0x43;*(z++)=y[x++]-0x0C;*(z++)=y[x++]+0x57;
*(z++)=y[x++]-0x08;*(z++)=y[x++]+0x03;*(z++)=y[x++]-0x06;
*(z++)=y[x++]-0x08;*(z++)=y[x++]-0x43;*(z++)=y[x]-0x21;
x=*(--z);while(y[x]!=NULL)putchar(y[x++]);
}

hello3.c

#include <stdio.h>
#define __(a) goto a;
#define ___(a) putchar(a);
#define _(a,b) ___(a) __(b);
main()
{ _:__(t)a:_('r',g)b:_('$',p)
c:_('l',f)d:_(' ',s)e:_('a',s)
f:_('o',q)g:_('l',h)h:_('d',n)
i:_('e',w)j:_('e',x)k:_('\n',z)
l:_('H',l)m:_('X',i)n:_('!',k)
o:_('z',q)p:_('q',b)q:_(',',d)
r:_('i',l)s:_('w',v)t:_('H',j)
u:_('a',a)v:_('o',a)w:_(')',k)
x:_('l',c)y:_('\t',g)z:___(0x0)}

hello4.c

int n[]={0x48,
0x65,0x6C,0x6C,
0x6F,0x2C,0x20,
0x77,0x6F,0x72,
0x6C,0x64,0x21,
0x0A,0x00},*m=n;
main(n){putchar
(*m)!='\0'?main
(m++):exit(n++);}

hello5.c

main(){int i,n[]={(((1<<1)<<(1<<1)<<(1<<
1)<<(1<<(1>>1)))+((1<<1)<<(1<<1))), (((1
<<1)<<(1<<1)<<(1<<1)<<(1<<1))-((1<<1)<<(
1<<1)<<(1<<1))+((1<<1)<<(1<<(1>>1)))+ (1
<<(1>>1))),(((1<<1)<<(1<<1)<<(1<<1)<< (1
<<1))-((1<<1)<<(1<<1)<<(1<<(1>>1)))- ((1
<<1)<<(1<<(1>>1)))),(((1<<1)<<(1<<1)<<(1
<<1)<<(1<<1))-((1<<1)<<(1<<1)<<(1<<(1>>1
)))-((1<<1)<<(1<<(1>>1)))),(((1<<1)<< (1
<<1)<<(1<<1)<<(1<<1))-((1<<1)<<(1<<1)<<(
1<<(1>>1)))-(1<<(1>>1))),(((1<<1)<<(1<<1
)<<(1<<1))+((1<<1)<<(1<<1)<<(1<<(1>>1)))
-((1<<1)<<(1<<(1>>1)))),((1<<1)<< (1<<1)
<<(1<<1)),(((1<<1)<<(1<<1)<<(1<<1)<<(1<<
1))-((1<<1)<<(1<<1))-(1<<(1>>1))),(((1<<
1)<<(1<<1)<<(1<<1)<<(1<<1))-((1<<1)<< (1
<<1)<<(1<<(1>>1)))-(1<<(1>>1))), (((1<<1
)<<(1<<1)<<(1<<1)<<(1<<1))- ((1<<1)<< (1
<<1)<<(1<<(1>>1)))+(1<<1)), (((1<<1)<< (
1<<1)<<(1<<1)<< (1<<1))-((1<<1)<< (1<<1)
<<(1<<(1>>1)))-((1<<1) <<(1<< (1>>1)))),
(((1<<1)<< (1<<1)<<(1<<1)<< (1<<1))- ((1
<<1)<<(1<<1)<<(1<<1))+((1<<1)<< (1<<(1>>
1)))), (((1<<1)<<(1<<1) <<(1<<1))+(1<<(1
>>1))),(((1<<1)<<(1<<1))+((1<<1)<< (1<<(
1>>1))) + (1<< (1>>1)))}; for(i=(1>>1);i
<(((1<<1) <<(1<<1))+((1 <<1)<< (1<<(1>>1
))) + (1<<1)); i++) printf("%c",n); }

hello6.cpp

下面的程序只能由C++的编译器编译(比如:g++)

#include <stdio.h>
#define _(_) putchar(_);
int main(void){int i = 0;_(
++++++++++++++++++++++++++++
++++++++++++++++++++++++++++
++++++++++++++++++++++++++++
++++++++++++++++++++++++++++
++++++++++++++++++++++++++++
++++i)_(++++++++++++++++++++
++++++++++++++++++++++++++++
++++++++++i)_(++++++++++++++
i)_(--++i)_(++++++i)_(------
----------------------------
----------------------------
----------------------------
----------------------------
----------------i)_(--------
----------------i)_(++++++++
++++++++++++++++++++++++++++
++++++++++++++++++++++++++++
++++++++++++++++++++++++++++
++++++++++++++++++++++++++++
++++++++++++++++++++++++++++
++++++++++++++++++++++++++i)
_(----------------i)_(++++++
i)_(------------i)_(--------
--------i)_(----------------
----------------------------
----------------------------
----------------------------
----------------------------
------i)_(------------------
----------------------------
i)return i;}

posted @ 2010-11-05 13:35 luzj 阅读(164) 评论(0) 编辑

问题: 目前在Qt开发环境中新建的项目名无法使用中文的.而创建的程序在程"应用程序"文件夹中建立的快捷方式是以项目名来显示的,这样就导致无法使用中文名了?

 

解决办法:被编译过的项目,在源码的文件夹下会产生*.loc文件(*为你的项目名),打开,修改为以下内容:

 

CHARACTER_SET UTF8
#ifdef LANGUAGE_SC

#define STRING_r_short_caption "中文名"

#define STRING_r_caption "中文名"

#else

#define STRING_r_short_caption "EnglishName"

#define STRING_r_caption "EnglishName"

#endif

 

 

然后保存,要用UTF-8编码来保存.

再在此文件上右键,加上只读属性即可,编译出来的程序在中文的系统上就会显示中文标题了.

posted @ 2010-10-27 15:16 luzj 阅读(240) 评论(0) 编辑

iPhone开发笔记()

---iPhone开发环境的安装

 

文章转载自我的博客:http://luzj.me/iphone-setup-and-helloworld.html


    今天讲讲iPhone开发环境的安装,目前在Windows上没有一个完善的iPhone开发平台,我们只能借助虚拟机安装Mac系统后在其上进行iPhone的开发,Mac的安装方法网络上介绍文章不少,以下安装过程不少图片来源于网络。

用的系统是 Mac os 10.6.3 ,开发环境是从Apple官网下载的xcode_3.2.4_and_ios_sdk_4.1

一、安装Mac

首先打开VMWare Workstation 7.1。使用File->New->Virtual Machine创建一个虚拟机,在选择操作系统时选择Other->FreeBSD 64-bit

 

 

创建好虚拟机之后,需要你在刚建立的虚拟机目录下找到一个扩展名为.vmx的文件,用记事本打开,找到 guestOS = "freebsd-64"一行,将引号里的freebsd-64改为darwin10,改完是guestOS = "darwin10",保存修改后的文件。

做了这一步,在这个虚拟机的Options->General选项下就可以看到操作系统版本显示为:MAC OS X Server 10.6,如下图所示。接下来我们就要开始安装了。安装的第一步是用Darwin.iso镜像进行引导。引导完成后插入MAC OS XDVD光盘。

此时,我们便进入了MAC OS X的安装程序准备阶段:

 

在屏幕上方的菜单中找到“实用工具”->“磁盘工具”,如图 所示:

 

对你的虚拟硬盘执行“抹掉”操作,如图所示:

 

操作完成后关闭“磁盘工具”窗口就可以进行安装了,根据你的电脑配置不同,大概进行几十分钟的安装,你就可以用上苹果操作系统了。

 

 

 

看到下图的界面,表示你的系统已经安装完成,需要重新启动。重新启动前先要去掉加载的苹果镜像,换上Darwin引导镜像。

 

 

重启之后,顺利的话你就会看到欢迎界面,进行简单的设置就能进入系统了。

 

打开光驱,安装VMware Tool

 

安装好后重启,给虚拟机设置共享盘

 

设置后就能在Mac下访问主机的文件了

 

二、安装iPhone SDK

Mac下去主机共享的文件夹中找到下载下来的xcode_3.2.4_and_ios_sdk_4.1.dmg文件,双击,系统会加载它

 

 

桌面会出现一个新的虚拟光驱,打开它,双击里面的mpkg文件,即可进入安装界面

 

 

安装过程简单就不抓图了,安装好后打开安装环境。

 

点击Create a new Xcode project,选择建立Window-based Application,点击Choose,输入项目名就进入了开发环境

 

在开发环境左边 Rescources 目录中找到 MainWindow.xib,双击,打开窗体编辑器,添加一个label,在上面写上几个字,保存,退出即可。

 

点击Build and Run 即可启动模拟器了。

 

 

此文为学习总结,若有不足之处望指出,谢谢!

posted @ 2010-10-27 14:50 luzj 阅读(2217) 评论(3) 编辑
摘要: 以下文字是工作中的总结,如有错误或者不足之处,望指出。不胜感激! 主要安装步骤说明: 以下带*号的要安装在同一个盘中,并且路径不能有空格和中文,否则。。。 1. 安装JDK 2. 安装ActivePerl-5.10 3. 安装Carbide_cpp_v2_3_en (*),装好后运行“程序\Nokia\Carbide.c++\Configure environment for WINSCW command line”,输入Y,按回车。 4. 安装Nokia_N97_SDK_v1_0_en(*),这个安装结束后会提示安装CSL Arm Toolchain,这个要装,路径默认即可。装好后运行“程序\Nokia Developer Tools\N97 SDK\v1.0\Languages\Change to Chinese”,可以将模拟器语言切换成中文。 5. 安装qt-symbian-opensource-4.7.0-s60.exe(*)阅读全文
posted @ 2010-10-24 23:56 luzj 阅读(1163) 评论(0) 编辑