Связать библиотеку внутри библиотеки с внешними элементами?

Я создаю библиотеку для взаимодействия с рисованием файлов определенного типа. Эта библиотека должна использовать стороннюю библиотеку, чтобы выполнить некоторую обработку этого конкретного типа файла. Эта сторонняя библиотека требует от пользователей создания некоторых внешних функций, которые она использует для создания типов данных на целевом оборудовании.

Итак, это выглядит так:

----------------
|              | 
| 3rd Party    | 
|   Lib        | 
|              | 
----------------
      |
      |
     \/
---------------
|             | 
|  My Lib     | 
---------------
|  externs    | 
---------------
      |
      |
     \/
---------------
|             | 
|  My App     | 
|             | 
|             | 
---------------

Мое приложение вызывает My Lib и говорит: «Нарисуй мне файл X», My Lib делает кучу мусора, в конечном итоге вызывая стороннюю Lib и говорит «обработать файл X». 3rd Party Lib требует, чтобы было объявлено несколько внешних модулей, которые она использует.

Я сделал все эти экстерны внутри My Lib. Моя проблема в том, что когда я связываю свое приложение, оно сообщает мне неопределенные ссылки на все внешние функции. Я не могу понять, почему. Вот один из внешних элементов внутри My Lib, который будет вызываться сторонней библиотекой:

// inside typeConversions.c

extern int CreateShort(short* shortList, int numShorts)
{
    int i;

    for(i = 0; i < numShorts; i++)
    {
        BYTE_SWAP_SHORT(shortList[i]);
    }

    return ERROR_OK;
}

Когда я связываю свое приложение, я получаю (среди нескольких других подобных ошибок):

open.cpp: неопределенная ссылка на CreateShort

Где open.cpp находится внутри сторонней библиотеки.

У меня есть и моя библиотека, и сторонняя библиотека, включенная в мое приложение. В идеале я хочу не предоставлять пользователям My Lib доступ к сторонним библиотекам, поэтому, например, My App вообще не должен включать сторонние библиотеки, они даже не знают, что они существуют. Все, что должно быть выставлено, это My Lib. Это возможно? Кто-нибудь знает, как решить мою проблему со ссылками?


person gooner15    schedule 29.11.2010    source источник
comment
stackoverflow.com/questions/2238456/how-does-cs -внешняя-работа   -  person nmichaels    schedule 29.11.2010


Ответы (2)


1) Найдите «соглашения о вызовах» в документации вашего компилятора и компоновщика. Скорее всего у вас несоответствие.

2) В C (не C++) ключевое слово extern следует использовать в заголовке, а не в определении функции. Убедитесь, что вы включили заголовок во все файлы, которые используют объявления, включая файл .C, который реализует то, что объявляет заголовок.

    // This goes in a header file
    extern int CreateShort(short* shortList, int numShorts)

    // This goes in a .c file.
    int CreateShort(short* shortList, int numShorts)
    {
        ...
        return ERROR_OK;
    }

3) Если вы используете C++ для написания функций, которые вызывает сторонняя библиотека, а сторонняя библиотека ожидает, что все будет работать как C, вам придется использовать extern "C", чтобы предотвратить искажение имен.

    // This goes in a header file
    extern "C" int CreateShort(short* shortList, int numShorts)
    // You can also wrap it in a block:
    // extern "C" {
    // int someFunc1( int x );
    // int someFunc2( int y );
    // }

    // This goes in a .cpp file.
    extern "C" int CreateShort(short* shortList, int numShorts)
    {
        ...
        return ERROR_OK;
    }
person JimR    schedule 29.11.2010
comment
Это чистый C, я пробовал extern C, а также объявлял extern в заголовке функции. Ни один из них не решает проблему, спасибо. Я использую Eclipse 3.3.0. У меня есть приложение, которое напрямую использует стороннюю библиотеку, создавая экстерны в самом приложении, которое связывается и работает нормально. Мне нужно, чтобы эта функциональность была в другой библиотеке, как я пытаюсь создать, но это не связано. - person gooner15; 30.11.2010
comment
@gooner15 Хорошо. Просмотрите документы вашего компилятора, чтобы узнать о соглашениях о вызовах. Насколько мне известно, Eclipse не является ни компилятором, ни компоновщиком. :) Если только он не попал в зону Emacs. Если вы работаете в Linux, попробуйте man gcc или info gcc и найдите соглашение о вызовах. Затем посмотрите на заголовки сторонних библиотек и посмотрите, какое соглашение о вызовах они ожидают. - person JimR; 30.11.2010
comment
Хорошо, я думаю, я не уверен, что я должен искать, поскольку соглашение о вызовах, похоже, касается только вызовов на разных языках? Я использую Cygwin в Eclipse, набор инструментов gcc с кросс-компилятором lynxos. Извините, у меня никогда не было таких проблем со ссылками, и я действительно не знаю, где искать. - person gooner15; 30.11.2010
comment
@ gooner15 Должен быть какой-то стандарт для того, как вещи называются, аргументы передаются функциям, кто извлекает стек при возврате и т. д. и т. д. и т. д. Эти вещи определяются соглашением о вызовах. Посмотрите на прототипы функций в заголовках сторонних библиотек и посмотрите, есть ли какие-либо операторы attribute, и опубликуйте их здесь. Я не уверен, каково соглашение о вызовах lynxos по умолчанию, поэтому, если вы сможете понять это, это поможет сузить круг проблем. - person JimR; 30.11.2010

Похоже, моя проблема заключалась в том, что у меня не было файла заголовка, содержащего мои экстерны, «видимого» достаточно, чтобы компоновщик мог видеть при связывании приложения. У меня есть несколько папок в рабочей области моей библиотеки, и перемещение файла заголовка в начало этой иерархии устранило мою проблему. Странный!

person gooner15    schedule 30.11.2010