Как избежать множественного определения ошибок? - PullRequest
8 голосов
/ 11 января 2011

Помимо перемещения функции hello() в другой исходный файл (.cpp) или переименования функции. Есть ли другие способы избежать ошибки компоновки?

staticLibA.h

#ifndef _STATIC_LIBA_HEADER
#define _STATIC_LIBA_HEADER

int hello(void);
int hello_staticLibA_only(void);

#endif

staticLibA.cpp

#include "staticLibA.h"

int hello(void)
{
    printf("\nI'm in staticLibA\n");
    return 0;
}

int hello_staticLibA_only(void)
{
    printf("\nstaticLibA: hello_staticLibA_only\n");
    return 0;
}

выход:

g++ -c -Wall -fPIC -m32 -o staticLibA.o staticLibA.cpp
ar -cvq ../libstaticLibA.a staticLibA.o
a - staticLibA.o

staticLibB.h

#ifndef _STATIC_LIBB_HEADER
#define _STATIC_LIBB_HEADER

int hello(void);
int hello_staticLibB_only(void);

#endif

staticLibB.cpp

#include "staticLibB.h"

int hello(void)
{
    printf("\nI'm in staticLibB\n");
    return 0;
}

int hello_staticLibB_only(void)
{
    printf("\nstaticLibB: hello_staticLibB_only\n");
    return 0;
}

выход:

g++ -c -Wall -fPIC -m32 -o staticLibB.o staticLibB.cpp 
ar -cvq ../libstaticLibB.a staticLibB.o 
a - staticLibB.o

main.cpp

extern int hello(void);
extern int hello_staticLibA_only(void);
extern int hello_staticLibB_only(void);

int main(void)
{
  hello();
  hello_staticLibA_only();
  hello_staticLibB_only();
  return 0;
}

выход:

g++ -c  -o main.o main.cpp
g++ -o multipleLibsTest main.o  -L. -lstaticLibA -lstaticLibB -lstaticLibC -ldl -lpthread -lrt
./libstaticLibB.a(staticLibB.o): In function `hello()':
staticLibB.cpp:(.text+0x0): multiple definition of `hello()'
./libstaticLibA.a(staticLibA.o):staticLibA.cpp:(.text+0x0): first defined here
collect2: ld returned 1 exit status
make: *** [multipleLibsTest] Error 1

Ответы [ 2 ]

11 голосов
/ 07 июня 2011

Поскольку вы, похоже, владеете обеими библиотеками, неясно, почему вы не можете переименовать функцию ...

В вашем main есть строка:

hello();

Что вы ожидаете здесь, если вы исправите ошибку компоновки? Должно ли оно вызывать реализацию в LibA или LibB? Полагаться на порядок передачи библиотек компоновщику, чтобы определить, какая функция связана, похоже на очень плохая идея . В реальном примере, что бы произошло, если бы ваша hello_staticLibB_only функция вызывала hello()? Это может привести к вызову версии функции из другой библиотеки ...

Поскольку вы используете g++, вам следует рассмотреть возможность помещения функций библиотеки в namespace (они предназначены для того, чтобы помочь вам избежать такого рода конфликтов имен). Это позволит как вашему коду, так и компоновщику определить разницу между методами.

Следуя этому подходу для LibA, вы получите:

staticLibA.h

#ifndef _STATIC_LIBA_HEADER
#define _STATIC_LIBA_HEADER

// Declare namespace to keep library functions together
namespace LibA {
    int hello(void);
    int hello_staticLibA_only(void);
}

#endif

staticLibA.cpp

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

// Indicate that contained function definitions belong in the LibA namespace
namespace LibA {
    int hello(void)
    {
        printf("\nI'm in staticLibA\n");
        return 0;
    }

    int hello_staticLibA_only(void)
    {
        printf("\nstaticLibA: hello_staticLibA_only\n");
        return 0;
    }
}

main.cpp

// These declarations would usually be in a header... but I've left
// them here to match your sample code...

// declare relevant functions to belong to the LibA namespace
namespace LibA{
    extern int hello(void);
    extern int hello_staticLibA_only(void);
}

// declare relevant functions from LibB (note they are not
// in a namespace)
extern int hello(void);
extern int hello_staticLibB_only(void);

int main(void)
{
    // Explicitly call the hello from LibA
    LibA::hello();
    // Call the other library function (also from LibA)
    LibA::hello_staticLibA_only();

    // Call library functions from LibB (note they don't require a namespace
    // because I haven't updated it to have one)
    hello();
    hello_staticLibB_only();
    return 0;
}
1 голос
/ 04 февраля 2011

Ошибка связывания, в частности, относится к привету.Это проявляется потому, что обе библиотеки предоставляют определения «привет».Здесь нет другой ошибки компоновки.

Вы можете поместить hello в отдельную библиотеку, hello находиться в отдельной библиотеке или просто иметь исполняемую ссылку на объектный файл hello [hello.o]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...