从Linux下的goahead-3.3.6版本移植到wince平台
官网文档表示可以直接支持,但是因为我们wince系统的裁剪
以及我当前开发环境是 visual studio 2005 ,而3.3.6版本需要2010版本后的vs才可以打开
所以直接从源码开始编译移植,并且部分接口在我们系统无法使用 需要重写
先知道需要知道有哪些.c/.cpp文件需要编译,可以通过阅读Linux下gcc编译日志查看
cc -shared -o build/linux-x64-default/bin/libgo.so
'-rdynamic'
'-Wl,--enable-new-dtags'
'-Wl,-rpath,$ORIGIN/'
-g -Lbuild/linux-x64-default/bin
"build/linux-x64-default/obj/action.o"
"build/linux-x64-default/obj/alloc.o"
"build/linux-x64-default/obj/auth.o"
"build/linux-x64-default/obj/cgi.o"
"build/linux-x64-default/obj/crypt.o"
"build/linux-x64-default/obj/file.o"
"build/linux-x64-default/obj/fs.o"
"build/linux-x64-default/obj/http.o"
"build/linux-x64-default/obj/js.o"
"build/linux-x64-default/obj/jst.o"
"build/linux-x64-default/obj/options.o"
"build/linux-x64-default/obj/osdep.o"
"build/linux-x64-default/obj/rom-documents.o"
"build/linux-x64-default/obj/route.o"
"build/linux-x64-default/obj/runtime.o"
"build/linux-x64-default/obj/socket.o"
"build/linux-x64-default/obj/upload.o"
"build/linux-x64-default/obj/est.o"
"build/linux-x64-default/obj/matrixssl.o"
"build/linux-x64-default/obj/nanossl.o"
"build/linux-x64-default/obj/openssl.o"
-lest -lest -lrt -ldl -lpthread -lm
其中删除掉ssl加密相关的接口, 只需要一个比较简单实用有基础功能的webs服务器即可
src/ssl/est.c, src/ssl/matrixssl.c, src/ssl/nanossl.c, src/ssl/openssl.c
加入了获取IP的接口
netconfig.c
就是下面的情况
其中源码中需要改动的接口有:
1 文件读写
2 获取文件大小以及文件修改时间
3 获取系统时间以及相关时间转换
4 设置和获取IP地址
1 文件读写
1>------ 已启动生成: 项目: goahead-3.3.6, 配置: Debug SDK1 (ARMV4I) ------
1>正在链接...
1> 正在创建库 SDK1 (ARMV4I)\Debug/goahead-3.3.6.lib 和对象 SDK1 (ARMV4I)\Debug/goahead-3.3.6.exp
1>libgo.lib(fs.obj) : error LNK2019: 无法解析的外部符号 close,该符号在函数 websCloseFile 中被引用
1>libgo.lib(upload.obj) : error LNK2001: 无法解析的外部符号 close
1>libgo.lib(fs.obj) : error LNK2019: 无法解析的外部符号 stat,该符号在函数 websStatFile 中被引用
1>libgo.lib(cgi.obj) : error LNK2001: 无法解析的外部符号 stat
1>libgo.lib(fs.obj) : error LNK2019: 无法解析的外部符号 read,该符号在函数 websReadFile 中被引用
1>libgo.lib(cgi.obj) : error LNK2001: 无法解析的外部符号 read
1>libgo.lib(fs.obj) : error LNK2019: 无法解析的外部符号 lseek,该符号在函数 websSeekFile 中被引用
1>libgo.lib(cgi.obj) : error LNK2001: 无法解析的外部符号 lseek
1>libgo.lib(fs.obj) : error LNK2019: 无法解析的外部符号 write,该符号在函数 websWriteFile 中被引用
1>libgo.lib(upload.obj) : error LNK2001: 无法解析的外部符号 write
1>libgo.lib(file.obj) : error LNK2001: 无法解析的外部符号 write
1>libgo.lib(cgi.obj) : error LNK2001: 无法解析的外部符号 write
1>libgo.lib(auth.obj) : error LNK2019: 无法解析的外部符号 time,该符号在函数 websOpenAuth 中被引用
1>libgo.lib(upload.obj) : error LNK2019: 无法解析的外部符号 unlink,该符号在函数 freeUploadFile 中被引用
1>libgo.lib(file.obj) : error LNK2001: 无法解析的外部符号 unlink
1>libgo.lib(cgi.obj) : error LNK2001: 无法解析的外部符号 unlink
1>libgo.lib(upload.obj) : error LNK2019: 无法解析的外部符号 getenv,该符号在函数 websUploadOpen 中被引用
1>libgo.lib(cgi.obj) : error LNK2019: 无法解析的外部符号 chdir,该符号在函数 cgiHandler 中被引用
1>libgo.lib(cgi.obj) : error LNK2019: 无法解析的外部符号 getcwd,该符号在函数 cgiHandler 中被引用
1>libgo.lib(cgi.obj) : error LNK2019: 无法解析的外部符号 CreateProcessA,该符号在函数 launchCgi 中被引用
1>libgo.lib(socket.obj) : error LNK2001: 无法解析的外部符号 errno
1>SDK1 (ARMV4I)\Debug/goahead-3.3.6.exe : fatal error LNK1120: 12 个无法解析的外部命令
1>生成日志保存在“file://e:\goahead.wince\goahead-3.3.6\goahead-3.3.6\SDK1 (ARMV4I)\Debug\BuildLog.htm”
1>goahead-3.3.6 - 22 个错误,0 个警告
========== 生成: 0 已成功, 1 已失败, 0 最新, 0 已跳过 ==========
需要把相关的open/write/read/close 改成 fopen/fwrite/fread/fclose
就需要把文件描述符(int)改成操作文件的指针(FILE*)了
对应的属性替换成FILE*
2 获取文件大小以及文件修改时间
time_t SystemTimeToTimet(SYSTEMTIME st){
FILETIME ft;
time_t pt;
LONGLONG nLL;
ULARGE_INTEGER ui;
SystemTimeToFileTime( &st, &ft );
ui.LowPart = ft.dwLowDateTime;
ui.HighPart = ft.dwHighDateTime;
nLL = (ft.dwHighDateTime << 32) + ft.dwLowDateTime;
pt = (long)((LONGLONG)(ui.QuadPart - 116444736000000000) / 10000000);
return pt;
}
PUBLIC int websStatFile(char *path, WebsFileInfo *sbuf)
{
WIN32_FILE_ATTRIBUTE_DATA lpFileInformation;
wchar_t wFilePath[64] = {L'0'};
char testPath[128];
int formatlength = 0;
int i = 0;
SYSTEMTIME systime;
WebsStat s;
ssize len = slen(path) - 1;
strcpy(testPath, path);
path = sclone(path);
if (path[len] == '/') {
path[len] = '\0';
} else if (path[len] == '\\') {
path[len - 1] = '\0';
}
wfree(path);
formatlength = strlen(testPath);
MultiByteToWideChar(CP_ACP,0,testPath,formatlength,wFilePath,formatlength+1);
GetFileAttributesEx(wFilePath, GetFileExInfoStandard, &lpFileInformation);
sbuf->size = (lpFileInformation.nFileSizeHigh << 32) | lpFileInformation.nFileSizeLow;
FileTimeToSystemTime(&lpFileInformation.ftLastWriteTime,&systime);
sbuf->mtime = SystemTimeToTimet(systime);
if(GetFileAttributesW(wFilePath)& FILE_ATTRIBUTE_DIRECTORY){
//dirrect
sbuf->isDir = 1;
}else{
sbuf->isDir = 0;
}
return 0;
}
3 相关时间转换 time_t和SYSTEMTIME的替换函数
time_t GetSystemTimet(){
SYSTEMTIME st;
FILETIME ft;
time_t pt;
LONGLONG nLL;
ULARGE_INTEGER ui;
//struct tm gm;
GetLocalTime( &st );
SystemTimeToFileTime( &st, &ft );
ui.LowPart = ft.dwLowDateTime;
ui.HighPart = ft.dwHighDateTime;
nLL = (ft.dwHighDateTime << 32) + ft.dwLowDateTime;
pt = (long)((LONGLONG)(ui.QuadPart - 116444736000000000) / 10000000);
return pt;
}
SYSTEMTIME TimetToSystemTime(time_t t){
FILETIME ft;
SYSTEMTIME pst;
LONGLONG nLL = Int32x32To64(t, 10000000) + 116445024000000000;
ft.dwLowDateTime = (DWORD)nLL;
ft.dwHighDateTime = (DWORD)(nLL >> 32);
FileTimeToSystemTime(&ft, &pst);
return pst;
}
GetLocalTime是一个Windows API 函数,用来获取当地的当前系统日期和时间
#include <iostream>
#include<time.h>
#include<windows.h>
#include<winbase.h>
using namespace std;
int main() {
SYSTEMTIME ltime;
GetLocalTime(<ime);
printf("the systemtime is:");
printf("%d/%02d/%02d %02d:%02d:%02d",ltime.wYear,ltime.wMonth,
ltime.wDay,ltime.wHour,ltime.wMinute,ltime.wSecond);
getchar();
return 0;
}
相对于Windows而言 Linux 没有提供特定的接口获取时间
Linux下一般是通过标C函数,来获取系统时间,当然window下也可以使用
#include <iostream>
#include<time.h>
#include<windows.h>
#include<winbase.h>
using namespace std;
int main() {
struct tm *t;
time_t tt;
time(&tt);
t=localtime(&tt);
printf("%d/%02d/%02d %02d:%02d:%02d\n",t->tm_year+1900,
t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
getchar();
return 0;
}
4 设置和获取IP地址
直接参考 http://blog.csdn.net/dreamintheworld/article/details/77935225
//http.c
static int setLocalHost(){
struct in_addr intaddr;
char host[128], ipaddr[128];
wchar_t UsbNetWorkName[32] = L"EMAC1";
NETWORK_ADPT_INFO tAdapterInfo = {0};
if (gethostname(host, sizeof(host)) < 0) {
//error("Cannot get hostname: errno %d", errno);
return -1;
}
struct hostent *hp;
if (GetIPAddress((wchar_t*)UsbNetWorkName,&tAdapterInfo)){
IPAddrToStr(ipaddr,tAdapterInfo.IPAddr);
}
websSetIpAddr(ipaddr);
websSetHost(ipaddr);
return 0;
}
5 配置文件的换行解析
auth.txt 和 route.txt 文件需要重新整理换行,修改linux下的\n(0x0A)为windows下面的 \r\n(0x0D,0x0A)
6 实现asctime
当前开发环境下编译器没有提供到asctime函数, 所以需要重新实现
char* asctime (const struct tm * timeptr).
返回字符串格式为 Wed Feb 13 15:46:11 2013
void format2asctime(char*result, time_t timeT){
char week[8] = {0};
char month[8] = {0};
SYSTEMTIME systime = TimetToSystemTime(timeT);
switch(systime.wMonth){
case 0: sprintf(month, "Jan");break;
case 1: sprintf(month, "Feb");break;
case 2: sprintf(month, "Mar");break;
case 3: sprintf(month, "Apr");break;
case 4: sprintf(month, "May");break;
case 5: sprintf(month, "Jun");break;
case 6: sprintf(month, "Jul");break;
case 7: sprintf(month, "Aug");break;
case 8: sprintf(month, "Sept");break;
case 9: sprintf(month, "Oct");break;
case 10: sprintf(month, "Nov");break;
case 11: sprintf(month, "Dec");break;
default: sprintf(month, "Jan");break;
}
switch(systime.wDayOfWeek){
case 0: sprintf(week, "Mon");break;
case 1: sprintf(week, "Tues");break;
case 2: sprintf(week, "Wed");break;
case 3: sprintf(week, "Thur");break;
case 4: sprintf(week, "Fri");break;
case 5: sprintf(week, "Sat");break;
case 6: sprintf(week, "Sun");break;
default: sprintf(week, "Mon");break;
}
sprintf(result, "%s %s %02d %02d:%02d:%02d %d", week, month, systime.wDay,
systime.wHour, systime.wMinute, systime.wSecond, systime.wYear);
}
7 创建进程函数CreateProcessA
报错: 1>libgo.lib(cgi.obj) : error LNK2019: 无法解析的外部符号 CreateProcessA,该符号在函数 launchCgi 中被引用
直接使用CreateProcess会调用到CreateProcessA, 需要手动修改宏定义为CreateProcessW
#define CreateProcess CreateProcessW//CreateProcessA
运行结果:
移植到Linux平台下的方法:
http://blog.csdn.net/dreamintheworld/article/details/75407076