буферы протокола + zlib = неразрешенный внешний символ

Моя программа (VS 2010) использует протокол Google Buffer Protocol, скомпилированный с включенной опцией HAVE_ZLIB. Я скомпилировал последнюю версию zlib и добавил .lib в свой проект, но во время связывания все равно получил

1> libprotobuf.lib (gzip_stream.obj): ошибка LNK2001: неразрешенный внешний символ _inflateEnd 1> libprotobuf.lib (gzip_stream.obj): ошибка LNK2001: неразрешенный внешний символ inflateInit2 1> libprotobuf.lib (gzip_stream .obj): ошибка LNK2001: неразрешенный внешний символ _inflate 1> libprotobuf.lib (gzip_stream.obj): ошибка LNK2001: неразрешенный внешний символ deflateInit2 1> libprotobuf.lib (gzip_stream.obj): ошибка LNK2001: неразрешенный внешний символ _deflate 1> libprotobuf.lib (gzip_stream.obj): ошибка LNK2001: неразрешенный внешний символ _deflateEnd

Я использовал dumpbin.exe /all zlib.lib, там написано:

Тип файла: БИБЛИОТЕКА

....

245 public symbols

....

 4DBE __imp__inflateInit2_@16
 4DBE _inflateInit2_@16

также в этом списке есть другие неразрешенные символы.

Что тогда не так? Почему компоновщик не может найти эти функции?

upd: после перекомпиляции zlib теперь __imp__inflateInit2_@4


person fogbit    schedule 13.09.2013    source источник
comment
Похоже, вы установили __stdcall в качестве соглашения о вызовах по умолчанию при сборке zlib (возможно, с /Gz переключателем компилятора), в то время как вызывающий код ожидает старый добрый __cdecl.   -  person Igor Tandetnik    schedule 13.09.2013
comment
@ Игорь Тандетник: только что проверил настройки, там __cdecl, нет опции /Gz в аргументах командной строки   -  person fogbit    schedule 13.09.2013
comment
dumpbin говорит об обратном. @16 является контрольным признаком искажения имени стандартного вызова. Еще одно, что нужно проверить: возможно, функции объявлены как-то вроде void ZLIBAPI inflateEnd(...), и макрос ZLIBAPI в конечном итоге расширяется до __stdcall в одном месте, но до __cdecl в другом.   -  person Igor Tandetnik    schedule 13.09.2013
comment
@IgorTandetnik: судя по тому, что я увидел в коде, он компилируется как __cdecl. Ш перекомпилировал его, и теперь dumpbin.exe говорит _inflateEnd@4, а не @16   -  person fogbit    schedule 13.09.2013
comment
Раньше вы смотрели на inflateInit2, а не на inflateEnd. Число после знака @ - это общее количество байтов, необходимых для всех параметров функции, поэтому, естественно, оно может быть разным для разных функций. Опять же, именно так работает украшение имени __stdcall (см. Раздел «Украшение имени» в этого документа )   -  person Igor Tandetnik    schedule 13.09.2013


Ответы (1)


Функции zlib определены как ZEXPORT. если ZLIB_WINAPI определен, то ZEXPORT определяется как __stdcall, иначе он не имеет значения, и все функции zlib по умолчанию определены как __cdecl.

Когда я скомпилировал zlib в VS2015, ZLIB_WINAPI был определен в проекте zlib, а в моем проекте c ++ ZLIB_WINAPI не был определен. поэтому мой проект ищет функции __cdecl в файле zlib .lib, а файл zlib .lib скомпилирован как __stdcall.

чтобы исправить это, вам нужно сообщить компилятору вашего проекта, что файл zlib .lib использует соглашение о вызовах __stdcall.

делать, используя:

#define ZLIB_WINAPI

до

#include "....\zlib.h"

в вашем проекте

person user1438233    schedule 06.10.2015
comment
Хотя этот ответ может быть правильным, пожалуйста, добавьте некоторые пояснения. Передача базовой логики важнее, чем просто предоставление кода, потому что это помогает OP и другим читателям исправить эту и подобные проблемы самостоятельно. - person CodeMouse92; 06.10.2015
comment
@ JasonMc92 Я добавил пояснение - person user1438233; 06.10.2015