• 在Windows平台上使用GCC编译C程序


            最近用 C 语言写了一个小程序,在设计时希望该程序在 Windows、Linux平台上都能够运行,所以使用宏来区分在不同操作系统下执行的语句。比如这个程序需要加载动态链接库,在包含头文件时,写法如下:
    #if defined(_WIN32) || defined(_WIN64)
      #include <windows.h>
    #else
      #include <dlfcn.h>  /* unix 或 linux 下包含与动态库加载、卸载有关函数的头文件名是 dlfcn.h */
    #endif

            加载动态链接库时,处理方法如下:

    #if defined(_WIN32) || defined(_WIN64)
      HINSTANCE dll_handle_for_win;
    /* 当操作系统为 windows 类型时,使用函数 LoadLibrary() 加载动态链接库 */
    #else
      void *dll_handle_for_unix_or_linux;
      char *error_statement;
    /* 当操作系统为 unix 或 linux 类型时,使用函数 dlopen() 加载动态链接库 */
    #endif
     
      int error_code;
      char dll_file_name[256];  /* dll_file_name 是要加载的动态链接库文件名 */
     
    /*********************************
      注意:这里省略了部分内容
    **********************************/
     
    /**************************************/
    // Load dynamic library
    #if defined(_WIN32) || defined(_WIN64)
      if ( !(dll_handle_for_win = LoadLibrary(dll_file_name)) )
      {
    #ifdef _DEBUG
        printf("load dynamic link library \'%s\' failed at %s, line %d!\n", dll_file_name, __FILE__, __LINE__);
        error_code = GetLastError();
        printf("LoadLibrary() function returned error code: 0x%x\n", error_code);
    #endif
        return (-1);
      }
    /**************************************/
    #else
      dlerror();
      if ( !(dll_handle_for_unix_or_linux = dlopen(dll_file_name, RTLD_LAZY)) )
      {
        error_statement = dlerror();
    #ifdef _DEBUG
        printf("load dynamic link library \'%s\' failed at %s, line %d!\n", dll_file_name, __FILE__, __LINE__);
        printf("Error statement: %s\n", error_statement);
    #endif
        return (-1);
      }
    #endif

            释放动态链接库时,处理方法如下:

    #if defined(_WIN32) || defined(_WIN64)
      FreeLibrary(dll_handle_for_win);
    #else
      dlclose(dll_handle_for_unix_or_linux);
    #endif

            在 64 位 Win7 下,用 Visual Studio 2010 编译、链接,能够生成可执行程序,程序能正常运行。接下来想知道在 Linux 下该程序能否编译,希望在 Windows 平台上先排除一下像拼写一类的小错误,可是手头暂时没有安装Linux 的计算机,这样就需要在 Windows 平台上用 GCC 编译一下这个程序,我的做法如下:

    1. 安装 MinGW;在 MinGW 的官网( http://mingw.org/ )上找到安装文件。
        下载链接为:
    https://nchc.dl.sourceforge.net/project/mingw/Installer/mingw-get-setup.exe
        注意:这个是 32 位的 MinGW,如果需要 64 位的 MinGW,
        下载网页是:
    MinGW-w64 - for 32 and 64 bit Windows download | SourceForge.net
        运行程序 mingw-get-setup.exe,安装时会看到是否同时安装图形用户界面支持( also install support for the graphical user interface )的提示,由于用不到,就取消了对这一项的勾选。安装时将 MinGW 安装到了默认目录 C:\MinGW 下。

    2. 安装GCC;按Windows组合键 Win + R,输入命令 cmd,启动命令提示符窗口。进入目录 C:\MinGW\bin\ ,执行命令:mingw-get install gcc
        这样就开始从网络上下载 GCC 相关的文件,安装完成后,
        执行命令:gcc --version ,将会看到 GCC 的版本号。如果想获取更多信息,可以执行命令:gcc -v

    3. 修改环境变量;“开始”按钮 -> 计算机 -> 菜单中的“系统属性” -> 高级系统设置,修改环境变量,在原有的 Path 后面添加以下内容:
        ;C:\MinGW\bin\

         修改完成后重启计算机。重启后,就可以在命令提示符窗口中,在任意路径下执行 gcc.exe 程序了。

    4. 编译 C 程序。由于当前阶段只想编译程序,不需要链接。进入命令提示符窗口,到程序所在目录下,执行gcc的命令

        格式如下:gcc -c 源代码文件名.c -I 头文件所在路径
        比如可以是:gcc -c test.c -I C:\testcode\include
        结果显示了一大堆错误和警告。仔细一看,好像编译报错的程序语句都处于 _WIN32 或 _WIN64 宏定义中包含的部分。我们此时的目的并不是要用 GCC 生成 Windows 下的可执行程序,而是想让 GCC 编译一下程序中能够在 Linux 平台上执行的那部分语句,检查那部分语句中是否存在语法等错误,但是现在 GCC 编译的还是在 Windows 平台上能执行的语句。为什么会这样?需要查看一下 GCC 编译时默认已定义了哪些宏。在网上查到查看 GCC 编译时默认宏的命令是:
    gcc -posix -E -dM - </dev/null
        可是该命令在 Windows 的命令提示符窗口中无法执行。这该怎么办呢?忽然想到这台计算机上安装过从
    Git for Windows 上下载的 git for windows。该程序自带了一个 Git Bash,如下图:


        到“开始”菜单中,启动 Git Bash,然后输入命令:gcc -posix -E -dM - </dev/null
        这下可以成功执行了,显示出当前 GCC 中定义的宏列表,如下图:

        果然使用 mingw-get 安装的 gcc 中,已经默认定义了 _WIN32 宏。在编译 C 程序时,想取消对 _WIN32 及 _WIN64 宏的定义,可以使用下面的命令:
    gcc -c test.c -I C:\testcode\include -U_WIN32 -U_WIN64
        还发现默认已定义的宏中没有包含 _DEBUG,在编译调试版程序时需要用到这个宏,可以使用下面的命令:
    gcc -c test.c -I C:\testcode\include -U_WIN32 -U_WIN64 -D_DEBUG

        用 GCC 编译时发现不再报告处于 _WIN32 或 _WIN64 宏定义中包含的语句错误了。接下来根据编译结果给出的提示,修改了一些拼写错误,成功生成了 test.o 文件,证明该 C 程序能够在 Linux 下通过编译。等将来有空时安装 Linux 虚拟机,再将 C 程序及其调用的动态库源程序都拿到 Linux 上编译链接,就能生成 Linux 上的可执行程序了。

    ------------------------

    说明
    gcc 编译选项:
    -c 只编译,不链接
    -D 使用指定的宏
    -U 取消指定的宏

     

    出处:https://blog.csdn.net/henter/article/details/54863462

  • 相关阅读:
    Map 中的EntrySet() ,Map的遍历
    Struts2拦截器原理
    基于 <tx> 和 <aop> 命名空间的声明式事务管理
    Spring AOP Example 文件下载:
    Struts2拦截器
    好多开发文档——官网打不开的福音
    threejs样例
    bootCDN,用了都说好
    react拷贝index.html很恶心之解决办法
    网络爬虫好
  • 原文地址:https://www.cnblogs.com/mq0036/p/15993413.html
Copyright © 2020-2023  润新知