(Обновление: согласно предложению Ганса, вот предложение по улучшению поведения link.exe
, и вы можете проголосовать за него, если у вас там есть аккаунт.)
Хорошо, я дурак. В январе я установил Oracle на свой компьютер, Win7 Pro 64 Bit. Я установил 64-битную версию. Вчера, используя MSVC Express, я попытался скомпилировать и связать небольшую тестовую программу oci1.c
против oci.h
и oci.lib
.
cl /nologo /c /I%ORACLE_HOME%\oci\include oci1.c
link /nologo oci1.obj /LIBPATH:%ORACLE_HOME%\oci\lib\msvc oci.lib
Мои попытки продолжали терпеть неудачу с LNK2019
, что означает неразрешенный внешний символ 'symbol', указанный в функции 'function' . Соответствующий символ (_OCIEnvCreate
), конечно, предоставляется oci.lib
, поэтому компоновщик должен иметь возможность его разрешить.
В конце концов меня осенило, что это не может работать, потому что мой компилятор только 32-битный, а библиотека импорта 64-битная. Если вы дурак и вы не знаете или не помните, то вы можете увидеть это с помощью утилиты dumpbin
:
$ dumpbin /headers %ORACLE_HOME%\oci\lib\msvc\oci.lib | head
File Type: LIBRARY
FILE HEADER VALUES
8664 machine (x64)
$ dumpbin /headers oci1.obj | head
File Type: COFF OBJECT
FILE HEADER VALUES
14C machine (x86)
Пока все хорошо. Но я потратил немного времени и хотел бы избежать повторения этого опыта.
Хотя это и не правильно, сообщение об ошибке LNK2019
не ведет вас прямо в правильном направлении. Нет никаких предупреждений о том, что вы пытаетесь связать двоичные файлы для разных архитектур ЦП.
Обратите внимание, что при указании архитектуры X64 вы получаете предупреждение о том, что вы указали двоичные файлы X86:
$ link /machine:x64 /nologo oci1.obj /LIBPATH:%ORACLE_HOME%\oci\lib\msvc oci.lib
oci1.obj : fatal error LNK1112:
Modul-Computertyp "X86" steht in Konflikt mit dem Zielcomputertyp "x64".
Но нет такого точного предупреждения, когда вы указываете архитектуру X86, явно или неявно:
$ link /machine:x86 /nologo oci1.obj /LIBPATH:%ORACLE_HOME%\oci\lib\msvc oci.lib
oci1.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol
"_OCIEnvCreate" in Funktion "_main".
oci1.exe : fatal error LNK1120: 1 nicht aufgelöste externe Verweise.
Я только что нашел переключатель / VERBOSE в link.exe
, который при использовании намекает на то, что в моем 64-битном oci.lib
.
символов нет.
Есть ли другие опции, которые вы можете включить, чтобы сделать процесс связывания более надежным?
Обновление : Согласно ответу Ганса, я запустил dumpbin
в 32-битной библиотеке импорта, и имена выглядят следующим образом:
$ dumpbin /exports D:\Opt\MySQL5.5\lib\libmysql.lib
_load_defaults
_myodbc_remove_escape@8
_mysql_affected_rows@4
_mysql_autocommit@8
_mysql_change_user@16
_mysql_character_set_name@4
Принимая во внимание, что имена в 64-битной библиотеке импорта OCI, с которыми я здесь работаю, выглядят недекорированными:
OCIXmlDbFreeXmlCtx
OCIXmlDbInitXmlCtx
ORLRconNativeInt
ORLRvalNativeInt
OraCoreIsPhysicalRawFile
OraMemAlloc
Википедия о соглашениях о вызовах X86 :
При компиляции для архитектуры x64 в контексте Windows (будь то
с использованием инструментов Microsoft или других производителей), есть только один вызов
конвенция - описанная здесь, так что stdcall, thiscall, cdecl,
fastcall и т. д. теперь все одно и то же.
Также имеет отношение к статье по искажению имен .
Имеет смысл для меня сейчас. Одно-единственное соглашение о вызовах, следовательно, нет необходимости в искажении имени, следовательно, нет начального подчеркивания согласно cdecl
при компиляции для X86.