移植版的 libuv:https://github.com/liigo/libuv-vc6 (支持VC6和XP,作者Liigo)。

我从一年前(大概2013年6,7月份)开始在业余时间做这项移植工作,走走停停,陆续用了一两个月的时间,才基本完成。这期间做了详细的移植记录,现在发布出来,希望对某些人有用。就在昨天(2014年7月12日),我又把移植的代码同步到最新的libuv(https://github.com/joyent/libuv)并发布到Github上;但是之前的移植记录没有变更,或许在一定程度上已经部分失效了。

我(Liigo)当初做这项移植工作的原始意图,是打算做一个封装 libuv 的易语言支持库。然而终究还没有做。理由是没有时间呢,缺乏需求呢,还是懒呢?我暂时不想下结论。

此移植版 libuv-vc6 的完整性和准确性尚未得到证明。但是我的tinyweb 已经基于该移植版编译,并且在Windows XP系统下运作正常。我想这能证明至少它是“基本可用”的。


VC6系统文件 MSWSOCK.H 编译时报错,说不认识“SOCKET”类型:
解决办法,在前面增加 typedef unsigned int  SOCKET;

uv-win.h 报错说 SRWLOCK 未定义,解决办法是在前面增加:
//http://blog.csdn.net/xiewneqi/article/details/4787156
typedef struct SRWLOCK {
void* ptr;
} SRWLOCK, *PSRWLOCK;

uv.h 未定义 sockaddr_storage,解决办法是在前面增加:
//http://stackoverflow.com/questions/1345109/why-sockaddr-storage-structure-defined-as-the-way-it-is-defined
struct sockaddr_storage {
short   ss_family;
char    __ss_pad1[6];
int64_t __ss_align;
char    __ss_pad2[112];
};

uv.h 报错说标识符 LPFN_CONNECTEX 语法错误,解决办法:
将 uv-win.h 内所有 " PASCAL (*" 替换为 " (PASCAL *" 。
把 LPFN_CONNECTEX 的定义从 uv-win.h 复制到 uv.h 报错行之前。

uv\src\winapi.h '_REPARSE_DATA_BUFFER'重定义,解决办法:删除定义,或注释掉/*defined(_MSC_VER) ||*/
ULONG_PTR 未定义,加入 typedef unsigned int* ULONG_PTR;

uv\src\winapi.h 未定义LPOVERLAPPED_ENTRY?加入以下代码:
typedef struct _OVERLAPPED_ENTRY {
  ULONG_PTR    lpCompletionKey;
  LPOVERLAPPED lpOverlapped;
  ULONG_PTR    Internal;
  DWORD        dwNumberOfBytesTransferred;
} OVERLAPPED_ENTRY, *LPOVERLAPPED_ENTRY;

缺少文件iptypes.h? 在下面链接下载后放到uv\src\win
http://stuff.mit.edu/afs/athena/astaff/project/opssrc/nmap-2.54BETA34/mswin32/IPTypes.h

ERROR_INVALID_REPARSE_DATA未定义?修改为 0x00001128/*ERROR_INVALID_REPARSE_DATA*/

INVALID_FILE_ATTRIBUTES未定义?修改为 (DWORD)-1/*INVALID_FILE_ATTRIBUTES*/

'bad suffix on number'?把数值后面的ULL删除即可(10000000ULL -> 10000000)

EAI_BADFLAGS等EAI_*未定义?加入以下代码:
/* Error codes from getaddrinfo() */
#define EAI_AGAIN           WSATRY_AGAIN
#define EAI_BADFLAGS        WSAEINVAL
#define EAI_FAIL            WSANO_RECOVERY
#define EAI_FAMILY          WSAEAFNOSUPPORT
#define EAI_MEMORY          WSA_NOT_ENOUGH_MEMORY
#define EAI_NOSECURENAME    WSA_SECURE_HOST_NOT_FOUND
//#define EAI_NODATA        WSANO_DATA
#define EAI_NONAME          WSAHOST_NOT_FOUND
#define EAI_SERVICE         WSATYPE_NOT_FOUND
#define EAI_SOCKTYPE        WSAESOCKTNOSUPPORT
#define EAI_IPSECPOLICY     WSA_IPSEC_NAME_POLICY_ERROR

addrinfo/addrinfoW未定义?在uv.h前面加入以下代码:
//http://msdn.microsoft.com/en-us/library/windows/desktop/ms737530(v=vs.85).aspx
typedef struct addrinfo {
  int             ai_flags;
  int             ai_family;
  int             ai_socktype;
  int             ai_protocol;
  size_t          ai_addrlen;
  char            *ai_canonname;
  struct sockaddr  *ai_addr;
  struct addrinfo  *ai_next;
} ADDRINFOA, *PADDRINFOA;
//http://msdn.microsoft.com/en-us/library/windows/desktop/ms737529(v=vs.85).aspx
typedef struct addrinfoW {
  int              ai_flags;
  int              ai_family;
  int              ai_socktype;
  int              ai_protocol;
  size_t           ai_addrlen;
  PWSTR            ai_canonname;
  struct sockaddr  *ai_addr;
  struct addrinfoW  *ai_next;
} ADDRINFOW, *PADDRINFOW;

WT_EXECUTELONGFUNCTION未定义?替换为 0x00000010/*WT_EXECUTELONGFUNCTION*/
WT_EXECUTEONLYONCE未定义?替换为 0x00000008/*WT_EXECUTEONLYONCE*/

in6_addr未定义?在错误提示行前加入以下代码:
struct in6_addr {
  u_char  s6_addr[16];
};

FILE_FLAG_FIRST_PIPE_INSTANCE未定义?替换为 0x00080000/*FILE_FLAG_FIRST_PIPE_INSTANCE*/

JOBOBJECT_EXTENDED_LIMIT_INFORMATION未定义?在前面加入以下代码:
typedef struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION {
  JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
  IO_COUNTERS                       IoInfo;
  SIZE_T                            ProcessMemoryLimit;
  SIZE_T                            JobMemoryLimit;
  SIZE_T                            PeakProcessMemoryUsed;
  SIZE_T                            PeakJobMemoryUsed;
} JOBOBJECT_EXTENDED_LIMIT_INFORMATION, *PJOBOBJECT_EXTENDED_LIMIT_INFORMATION;

IO_COUNTERS未定义?在前面加入以下代码:
typedef struct _IO_COUNTERS {
  ULONGLONG ReadOperationCount;
  ULONGLONG WriteOperationCount;
  ULONGLONG OtherOperationCount;
  ULONGLONG ReadTransferCount;
  ULONGLONG WriteTransferCount;
  ULONGLONG OtherTransferCount;
} IO_COUNTERS, *PIO_COUNTERS;

JOB_OBJECT_LIMIT_BREAKAWAY_OK等未定义?在前面加入以下代码:
#define JOB_OBJECT_LIMIT_SCHEDULING_CLASS       0x80
#define JOB_OBJECT_LIMIT_PROCESS_MEMORY         0x100
#define JOB_OBJECT_LIMIT_JOB_MEMORY             0x200
#define JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION 0x400
#define JOB_OBJECT_LIMIT_BREAKAWAY_OK           0x800
#define JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK    0x1000
#define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE      0x2000

NOINLINE未被识别?替换为 /*NOINLINE*/

((ULONG_PTR) req->event_handle | 1) 语法错误? 改为 ((DWORD) req->event_handle | 1)

IPPROTO_IPV6未定义?替换为 41/*IPPROTO_IPV6*/

IPV6_MULTICAST_HOPS未定义?替换为 10/*IPV6_MULTICAST_HOPS*/
IPV6_MULTICAST_LOOP未定义?替换为 11/*IPV6_MULTICAST_LOOP*/

WSAID_CONNECTEX未定义?替换为 {0x25a207b9,0xddf3,0x4660,{0x8e,0xe9,0x76,0xe5,0x8c,0x74,0x06,0x3e}}/*WSAID_CONNECTEX*/

JobObjectExtendedLimitInformation未定义?替换为 9/*JobObjectExtendedLimitInformation*/

UnregisterWait,UnregisterWaitEx,RegisterWaitForSingleObject等未定义?在winapi.h中加入以下代码:
typedef BOOL (WINAPI* sUnregisterWait) (HANDLE WaitHandle);
typedef BOOL (WINAPI* sUnregisterWaitEx) (HANDLE WaitHandle, HANDLE CompletionEvent);
typedef VOID (CALLBACK* WAITORTIMERCALLBACK) (PVOID lpParameter, BOOLEAN TimerOrWaitFired);
typedef BOOL (WINAPI* sRegisterWaitForSingleObject)
             (PHANDLE phNewWaitObject,
              HANDLE hObject,
              WAITORTIMERCALLBACK Callback,
              PVOID Context,
              ULONG dwMilliseconds,
              ULONG dwFlags);
然后在winapi.h/.c中参考原有代码补充必需的代码(定义函数指针变量、对其赋值等),然后把对UnregisterWait的调用改为pUnregisterWait(其他类推)。
对于其他在链接时找不到符号的Windows API函数,一并做如上处理。对于GetProcessMemoryInfo函数要做特殊处理,在两个系统DLL去找其实现函数地址:
-----------------------------------------------------
  //http://msdn.microsoft.com/en-us/library/windows/desktop/ms683219(v=vs.85).aspx
  pGetProcessMemoryInfo = (sGetProcessMemoryInfo)
    GetProcAddress(kernel32_module, "GetProcessMemoryInfo");
  if(pGetProcessMemoryInfo == NULL) {
    pGetProcessMemoryInfo = (sGetProcessMemoryInfo)
      GetProcAddress(GetModuleHandleA("Psapi.dll"), "GetProcessMemoryInfo");
  }
-----------------------------------------------------

找不到IPHlpApi.h?在这里下载:
https://docs.google.com/file/d/0B-VpknkVIm1fdnNabE1ScmlLazQ/edit?usp=sharing
为防止“重复定义IN6_ADDR”的编译错误,需要在 #include "Iphlpapi/iphlpapi.h" 之前先 #define s6_addr 。

找不到psapi.h?在这里下载:
https://docs.google.com/file/d/0B-VpknkVIm1fU3pDRTBDM3JXOWM/edit?usp=sharing

GlobalMemoryStatusEx未定义?在winapi.h加入以下代码:
typedef struct _MEMORYSTATUSEX {
  DWORD     dwLength;
  DWORD     dwMemoryLoad;
  DWORDLONG ullTotalPhys;
  DWORDLONG ullAvailPhys;
  DWORDLONG ullTotalPageFile;
  DWORDLONG ullAvailPageFile;
  DWORDLONG ullTotalVirtual;
  DWORDLONG ullAvailVirtual;
  DWORDLONG ullAvailExtendedVirtual;
} MEMORYSTATUSEX, *LPMEMORYSTATUSEX;
typedef BOOL (WINAPI* sGlobalMemoryStatusEx) (LPMEMORYSTATUSEX lpBuffer);
然后在winapi.h/.c中参考原有代码补充必需的代码(定义函数指针变量、对其赋值等),然后把对GlobalMemoryStatusEx的调用改为pGlobalMemoryStatusEx。

IP_ADAPTER_UNICAST_ADDRESS_XP未定义?替换为IP_ADAPTER_UNICAST_ADDRESS,然后
#include "Iphlpapi/iptypes.h" (来源见上文)
因为该头文件中定义的IP_ADAPTER_UNICAST_ADDRESS实质上就是IP_ADAPTER_UNICAST_ADDRESS_XP。

wmemcmp未定义?把原代码 wmemcmp(data_block->Signature, L"PERF", 4) 修改为:
memcmp(data_block->Signature, L"PERF", 4 * sizeof(TCHAR))

IF_TYPE_SOFTWARE_LOOPBACK未定义?替换为 24/*IF_TYPE_SOFTWARE_LOOPBACK*/

'sin6_scope_id' : is not a member of 'sockaddr_in6'? 注释掉 uv-win.h 内的宏定义 UV_PLATFORM_HAS_IP6_LINK_LOCAL_ADDRESS。
或者加入下面的定义:
/* The ws2tcpip.h header included in VC6 doesn't define the
 * sin6_scope_id member of sockaddr_in6.  We define our own
 * version and redefine sockaddr_in6 to point to this one.
 */
struct liigo_sockaddr_in6 {
  short sin6_family;
  u_short sin6_port;
  u_long sin6_flowinfo;
  struct in6_addr sin6_addr;
  u_long sin6_scope_id;
};
#define sockaddr_in6 liigo_sockaddr_in6

调用swprintf参数过多?swprintf(path2, len + 3, fmt, pathw)改为swprintf(path2, fmt, pathw)

_set_invalid_parameter_handler是VC2005才加入到CRT函数,VC6里面没有。在libuv源代码里面直接注释掉对该函数的调用即可。

_BitScanReverse未定义?在前面加入以下代码,然后删除VC下对_BitScanReverse的调用,统一用GCC版代码即可:
//http://stackoverflow.com/questions/355967/how-to-use-msvc-intrinsics-to-get-the-equivalent-of-this-gcc-code
#ifndef __GNUC__
static unsigned int __declspec(inline) popcnt( unsigned int x )
{
    x -= ((x >> 1) & 0x55555555);
    x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
    x = (((x >> 4) + x) & 0x0f0f0f0f);
    x += (x >> 8);
    x += (x >> 16);
    return x & 0x0000003f;
}
static unsigned int __declspec(inline) __builtin_clz( unsigned int x )
{
    x |= (x >> 1);
    x |= (x >> 2);
    x |= (x >> 4);
    x |= (x >> 8);
    x |= (x >> 16);
    return 32 - popcnt(x);
}
static unsigned int __declspec(inline) __builtin_ctz( unsigned int x )
{
    return popcnt((x & -x) - 1);
}
#endif
另外一个模拟实现_BitScanReverse的思路也是可行的:http://bbs.csdn.net/topics/350202744

_InterlockedOr8未定义?重新实现uv__atomic_exchange_set如下:
static char __declspec(inline) uv__atomic_exchange_set(char volatile* target) {
  //return _InterlockedOr8(target, 1);
  __asm mov ecx, target
  __asm mov al, byte ptr [ecx]
  __asm lock or byte ptr [ecx], 1
}

_aligned_malloc, _aligned_free, 等函数未定义?自己实现这两个函数,代码如下:
static void* _aligned_malloc(unsigned int size, unsigned int align) {
  unsigned int rem;
  unsigned char *op, *np;
  op = (unsigned char*) malloc(size + align);
  if(op == NULL) return NULL;
  rem = (unsigned int)op % align;
  np = op + align - rem;
  *(np-1) = (unsigned char)align - rem;
  return np;
}
static void _aligned_free(void* p) {
  if(p) {
    unsigned char n = *((unsigned char*)p - 1);
    free((unsigned char*)p - n);
  }
}

InterlockedCompareExchangePointer在新版VC中是编译器生成的函数,并不存在于kernel.dll里面,而VC6显然不可能生成该函数。解决办法:
pInterlockedCompareExchangePointer = (sInterlockedCompareExchangePointer) GetProcAddress(kernel32_module, "InterlockedCompareExchange");
//VC6 always create x86 programs. 因为VC6总是生成32位程序,不可能调用64位版的函数。

缺少常量IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP?在前面加入如下代码:
#ifndef IPPROTO_IPV6
#define IPPROTO_IPV6 41
#endif

#ifndef IPV6_MULTICAST_IF
#define IPV6_MULTICAST_IF 9
#endif
#ifndef IPV6_ADD_MEMBERSHIP
#define IPV6_ADD_MEMBERSHIP 12
#endif
#ifndef IPV6_DROP_MEMBERSHIP
#define IPV6_DROP_MEMBERSHIP 13
#endif

常量ERROR_INVALID_REPARSE_DATA没定义?改成下面这样:
4392/*ERROR_INVALID_REPARSE_DATA*/

移植 libuv 到 Visual C++ 6.0 并支持在 Windows XP 系统下编译相关推荐

  1. 如何将windows xp系统下的outlook express6.0的邮件,帐号及通迅录导入Office Outlook xp/2003/2007中

    如何将windows xp系统下的outlook express6.0的邮件,帐号及通迅录导入Office Outlook xp/2003/2007中 1.此帮助以Outlook express6.0 ...

  2. 目标检测第5步:如何在Windows 10系统下,搭建YOLOv5(5.0)环境?保姆级,没有人比这个更详细了(更新时间2022.3.22)

    (请先看置顶博文)本博打开方式!!!请详读!!!请详读!!!请详读!!!_Cat-CSDN博客 目录 一.安装Anaconda或Miniconda 二.安装CUDA 三.安装cuDNN 四.安装Pyt ...

  3. centos 6 mysql 5.7.13 编译安装_Centos 6.5系统下编译安装PHP 7.0.13的方法

    PHP7.0正式版也出来了,今天编译安装了一下,写下安装步骤,我是在centos6.6 环境中编译的,下面是详细的安装步骤 环境依赖 yum install gcc gcc-c++ libxml2 l ...

  4. 基于QtQuick2.0应用程序运行于XP系统的诸多问题

    (20160330)基于QtQuick2.0应用程序运行于XP系统的诸多问题 客户端 使用QtQuick技术开发酷炫的XP客户端经常遇到白屏或者无界面 if Qt is built using ANG ...

  5. 最完整VC++6.0安装教程、windows命令行cl编译命令配置、cl编译命令使用、以及整套安装所需的附件

    最近电脑出了问题,还原了系统.要重新配置包括JDK.JRE.eclipse.mysql等等各种环境和工具,其中配置cl编译命令时发现和以前配置的时候不太一样,折腾了一会儿.现在给出完整的教程. 说明: ...

  6. Windows XP环境下Apache2.2.21和Tomcat7.0.26下的整合

    用到这个纯属偶然吧,实训的进行系统设计时自己觉得用下Apache和Tomcat整合下较好.因此网上查找了一些,自己实现了一下.我们都知道Tomcat 应用于服务器JSP处理是比较强的,但遇到一些诸如H ...

  7. 天正安装autocad启动失败_天正T20-V2.0版本,在WIN764位系统下运行AUTOCAD2007 不成功,提示AUTOCAD启动失败...

    把天正的sys19x64(有时候为2113sys18x64)文件夹里的文件tch_AdoShell.exe的属性做5261调整:以管理员的身4102份运行1653即可.这样操作以后,问题就解决了.记得 ...

  8. Windows 10系统下WeBug4.0靶场搭建

    最近在搭建webug4.0靶场时遇到一些蒙圈的问题,由于很长时间没有搭建过靶场了,在此简单记录一下. 资源链接:https://pan.baidu.com/s/1q8yKkmMALJsuvLegZq9 ...

  9. 【只需4步】windows server系统下快速安装绿色版apache-tomcat-8.0.35(免安装版)

    戳https://mirrors.bfsu.edu.cn/apache/tomcat/tomcat-8/v8.5.60/bin/apache-tomcat-8.5.60.zip 下载好了解压到你一个不 ...

  10. 安卓9.0刷linux,Ubuntu系统下编译Android 9.0系统

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 前言 在Ubuntu系统下编译Android系统.哎呀不知道是不是换了新电脑的缘故,这次编译居然从安装JDK和配置环境下 ...

最新文章

  1. html向js传递id
  2. windows 2008本地计算机策略,windows2008组策略操作出现了扩展错误 未能保存本地策略数据库#...
  3. 看printk引发的一点思考
  4. 产品经理学SQL—前言
  5. Android 安全(1)---概述
  6. [NOIp2016]天天爱跑步 线段树合并
  7. JqGrid常用示例
  8. tensorflow搭建神经网络
  9. TCP新手误区–粘包的处理
  10. LanguageTool最简范例代码
  11. 大数据数据仓库-简介
  12. 使用qemu进行路由器环境的虚拟搭建
  13. ubuntu踩坑笔记--开机进入recovering journal解决方法
  14. NodeMCU开发板详解(ESP8266开发篇)
  15. 收集各种文章资料的URL 不断更新
  16. FIFO深度计算公式
  17. TCPIP技术实验大作业:基于TCP/IP的程序开发技术综述及应用实践
  18. ubuntu18.0.4编译ffmpeg开启qsv硬件编解码
  19. Sage X3 PJM结构分解示例详解
  20. 2020-用多通道卷积神经网络学习单类特征用于人脸表现攻击检测

热门文章

  1. 2020最新Java高级工程师学习路线
  2. 易语言之今日头条新闻收集源码
  3. Python技能树测评之改进建议
  4. 青岛鑫江东方城购物中心远程预付费电能管理系统的应用
  5. 程序猿必备的数电知识,快来看看你掌握多少!(建议收藏)
  6. 教大家如何选购直播声卡
  7. 虚拟环境下iperf安装及打流测试
  8. 数字图像处理与机器视觉,机器视觉算法与应用 pdf电子版
  9. Java -jar与-class反编译工具procyon-decompiler的下载与使用
  10. (查看dll函数名和参数)通过VS自带的dumpbin查看dll包含的函数