(更新:根据汉斯的建议,这里有一个改善link.exe
行为的建议,如果你在那边有账号可以投票给它。)
好吧,我是个傻瓜。一月份,我在我的电脑上安装了 Oracle,Win7 Pro 64 位。我安装了 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
我的尝试一直以 'function' 失败LNK2019
,这意味着函数 'function' 中引用了未解析的外部符号 'symbol'。当然,有问题的符号 ( _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
错误消息不会引导您朝着正确的方向前进。没有警告您正在尝试链接不同 CPU 架构的二进制文件。
请注意,当您指定 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
。
您是否可以打开其他选项以使链接过程更加,嗯,万无一失?
更新:根据 Hans 的回答,我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
在 Windows 上下文中为 x64 架构编译时(无论是使用 Microsoft 还是非 Microsoft 工具),只有一种调用约定 — 此处描述的一种,因此 stdcall、thiscall、cdecl、fastcall 等现在都是一个和相同的。
还与有关名称修饰的文章有关。
现在对我来说很有意义。cdecl
一个也是唯一的调用约定,因此不需要名称修饰,因此在为 X86 编译时没有前导下划线。