检查系统是否实现了某个功能

时间:2017-02-18 03:42:04

标签: c function cross-platform

我正在创建一个跨系统的应用程序。例如,它使用函数textLines,它在某些系统上实现,但不是全部。如果我只是提供自己的itoa实现:

itoa

我知道我可以检查宏是否是预定义的,如果没有,则定义它们:

header.h:115:13: error: conflicting types for 'itoa'
 extern void itoa(int, char[]);

In file included from header.h:2:0,
                 from file.c:2:0,
c:\path\to\mingw\include\stdlib.h:631:40: note: previous declaration of 'itoa' was here
 _CRTIMP __cdecl __MINGW_NOTHROW  char* itoa (int, char*, int);

有没有办法检查C函数是否已预先实现,如果没有,请实现它?或者只是简单地实现一个函数?

4 个答案:

答案 0 :(得分:6)

鉴于您已经编写了自己的&实现,我建议您重命名并在任何地方使用它。至少你确定你会在所有平台上获得相同的行为,并避免链接问题。

不要忘记在您的代码的评论中解释您的选择......

答案 1 :(得分:4)

我假设你正在使用GCC,因为我可以在你的路径中看到MinGW ...... GNU链接器可以通过哪种方式为你处理这个问题。所以你不知道是否有itoa实施。试试这个:

创建一个名为my_itoa.c的新文件(没有任何标题):

char *itoa (int, char *, int);

char *my_itoa (int a, char *b, int c)
{
    return itoa(a, b, c);
}

现在创建另一个文件impl_itoa.c。在这里,编写itoa的实现,但添加一个弱别名:

char* __attribute__ ((weak)) itoa(int a, char *b, int c)
{
     // implementation here
}

编译所有文件,最后加impl_itoa.c

这样,如果标准库中没有itoa,则会链接此标准库。你可以自信地编译它是否可用。

答案 2 :(得分:2)

Ajay Brahmakshatriya's suggestion是一个很好的,但不幸的是MinGW在我检查后不支持弱定义(例如,参见https://groups.google.com/forum/#!topic/mingwusers/44B4QMPo8lQ)。

但是,我认为弱引用在MinGW中起作用。拿这个最小的例子:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

__attribute__ ((weak)) char* itoa (int, char*, int);

char* my_itoa (int a, char* b, int c)
{
    if(itoa != NULL) {
        return itoa(a, b, c);
    } else {
        // toy implementation for demo purposes
        // replace with your own implementation
        strcpy(b, "no itoa");
        return b;
    }        
}

int main()
{
    char *str = malloc((sizeof(int)*3+1));

    my_itoa(10, str, 10);
    printf("str: %s\n", str);
    return 0;
}

如果系统提供itoa实现,则应使用该输出,输出将为

  

str:10

否则,你会得到

  

str:no itoa

答案 3 :(得分:0)

这里有两个非常重要的相关要点:“不要这样做”这一行:

  • 请勿使用atoi,因为it's not safe
  • 不要使用atoi因为它不是标准功能,并且有很好的标准功能(例如snprintf)可以做你想要的。

但是,把所有这些放在一边,我想向你介绍autoconf, part of the GNU build system。 autoconf是一套非常全面,非常便携的工具的一部分,旨在使编写代码更容易,这些代码可以在各种目标系统上成功构建。有些人认为autoconf系统太复杂,无法解决你只用一个库函数造成的一个问题,但随着任何程序的增长,它可能会面临更多这样的障碍,并且为你的程序设置autoconf现在会放你处于一个更强大的未来地位。

从名为Makefile.in的文件开始,其中包含:

CFLAGS=--ansi --pedantic -Wall -W

program: program.o
program.o: program.c

clean:
  rm -f program.o program

以及名为configure.ac的文件,其中包含:

AC_PREREQ([2.69])
AC_INIT(program, 1.0)
AC_CONFIG_SRCDIR([program.c])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.
AC_PROG_CC

# Checks for library functions.
AH_TEMPLATE([HAVE_ITOA], [Set to 1 if function atoi() is available.])
AC_CHECK_FUNC([itoa],
              [AC_DEFINE([HAVE_ITOA], [1])]
              )

AC_CONFIG_FILES([Makefile])
AC_OUTPUT

以及名为program.c的文件,其中包含:

#include <stdio.h>
#include "config.h"

#ifndef HAVE_ITOA

/*
 * WARNING: This code is for demonstration purposes only. Your
 * implementation must have a way of ensuring that the size of the string
 * produced does not overflow the buffer provided.
 */

void itoa(int n, char* p) {
  sprintf(p, "%d", n);
}
#endif

int main(void) {
  char buffer[100];
  itoa(10, buffer);
  printf("Result: %s\n", buffer);
  return 0;
}

现在依次运行以下命令:

  1. autoheader:这会生成一个名为config.h.in的新文件,我们稍后会需要这个文件。
  2. autoconf:这会生成一个名为configure
  3. 的配置脚本
  4. ./configure:这会运行一些测试,包括检查你是否有一个正常工作的C编译器,因为我们已经问过它,itoa函数是否可用。它将结果写入文件config.h以供日后使用。
  5. make:这会编译并链接该程序。
  6. ./program:这最终运行程序。
  7. ./configure步骤中,您会看到很多输出,包括:

    checking for itoa... no
    

    在这种情况下,您会看到config.h查找包含以下行:

    /* Set to 1 if function atoi() is available. */
    /* #undef HAVE_ITOA */
    

    或者,如果你atoi可用,你会看到:

    checking for itoa... yes
    

    ,这在config.h

    /* Set to 1 if function atoi() is available. */
    #define HAVE_ITOA 1
    

    您会看到该程序现在可以阅读config.h标题,并选择定义itoa,如果它不存在。

    是的,解决问题还有很长的路要走,但您现在已经开始使用一个非常强大的工具,可以通过多种方式为您提供帮助。

    祝你好运!