Ссылка на статическую библиотеку C ++ из приложения Qt - PullRequest
0 голосов
/ 08 августа 2011

Я пытаюсь связать статическую библиотеку не-Qt с приложением на основе Qt (это проект Visual Studio).
Проблема в том, что у статической библиотеки есть некоторые API, которые принимают указатель на строку TCHARв качестве одного из входов.Когда я пытаюсь построить проект, я получаю ошибку компоновки с жалобой на TCHAR.

Заголовок

class Test
{
  public:
  static bool TestFunc( TCHAR *empty );
};

Источник

bool Test::TestFunc( TCHAR *empty )
{
  return true;
}

Ошибка:

error LNK2019: unresolved external symbol "public: static bool __cdecl Test::TestFunc(unsigned short *)" (?TestFunc@Test@@SA_NPAG@Z) referenced in function "public: __thiscall TestApp::TestApp(class QWidget *,class QFlags<enum Qt::WindowType>)" (??0TestApp@@QAE@PAVQWidget@@V?$QFlags@W4WindowType@Qt@@@@@Z)

Интересно то, что если у меня есть реализация функции в заголовочном файле, она работает нормально.Или, если я изменю TCHAR на обычный символ и оставлю объявление / определение отдельно, это также сработает (использование wchar_t напрямую приводит к ошибке с той же ошибкой компоновки).

Кто-нибудь знает, что может вызвать эту проблему, икак это решить?
Заранее спасибо,

Ответы [ 4 ]

3 голосов
/ 09 августа 2011

Что использовала статическая библиотека?Визуальная студия?Какая версия?

Я попытаюсь объяснить возникшую проблему.

Прежде всего, причина, по которой это работает, когда вы помещаете тело функции в заголовок, заключается в том, что это, по сути, вызывает тело функции.быть перекомпилированным вашим приложением.На самом деле компоновщику больше не нужно разрешать какие-либо символы из статической библиотеки.Следовательно, проблема с компоновщиком исчезла.

Проблема в том, что когда статическая библиотека была скомпилирована, компилятором была экспортирована функция, которую она экспортирует Test::TestFunc (по сути, она переименовывает ее в соответствии с некоторой внутренней схемой).Перенос имени функции - это то, что делает компилятор, чтобы упростить разрешение символов для компоновщика.Способ искажения имени функции не определен в соответствии со стандартом c ++.Поэтому разные компиляторы с разными настройками будут по-разному манипулировать именами функций.

Когда вы пытаетесь создать приложение, связывающее эту библиотеку, Visual Studio теперь манипулирует функцией там, где она называется (вероятно, в main()).Если искажение имени статической библиотеки, в которой определена функция, не совпадает с искажением имени, из которого вызывается функция, то вы получите ошибку, которую получили.То есть, компоновщик будет искать функцию X в статической библиотеке, и все, что он может найти, это функция Y.

Теперь, как указывали другие авторы, искажение имени также зависит отпараметры, которые функция принимает в качестве входных данных.Если типы параметров различаются в двух местах (определение и использование), компилятор будет по-разному манипулировать именами функций.Поэтому, опять же, компоновщик не сможет разрешить совпадение.

Суть в том, что в обоих местах, где существует символ (библиотека и приложение), символ ДОЛЖЕН бытьизуродованы одинаково.Лучший способ сделать это - это скомпилировать с использованием точно такого же компилятора с точно такими же настройками.

Другая возможность, конечно, заключается в том, что символ фактически не существует в статической библиотеке, с которой вы ссылаетесь!

2 голосов
/ 08 августа 2011

Убедитесь, что настройки компилятора одинаковы для обоих проектов.В частности, посмотрите на свойство «Набор символов», убедитесь, что они оба Unicode.Это изменяет определение макроса TCHAR.

1 голос
/ 09 августа 2011

По умолчанию VS компилируется с включенным «Обрабатывать wchar_t как встроенный тип» (/Zc:wchar_t).Qt компилируется с отключенной опцией (/Zc:wchar_t-).Если вы отключите «Обрабатывать wchar_t как встроенный тип» в VS (в разделе «Свойства конфигурации> C / C ++> Язык»), перед сборкой статической библиотеки это исправит?

0 голосов
/ 08 августа 2011

TCHAR - это char или wchar (то есть utf16) в зависимости от того, как построено приложение.

edit: если вы хотите смешать тип стрига Qt с TCHAR
Просто преобразуйте вашу QString в local8bit или utf16 () и затем приведите результат к TCHAR*

И преобразовать обратно из TCHAR в QString

QString toQString(const char *str) { return QString::fromLocal8Bit(str); }
QString toQString(const wchar_t *str) { return QString::fromWCharArray(str); }
...