3

(更新:根据汉斯的建议,这里有一个改善link.exe行为的建议,如果你在那边有账号可以投票给它。)


好吧,我是个傻瓜。一月份,我在我的电脑上安装了 Oracle,Win7 Pro 64 位。我安装了 64 位版本。昨天,使用 MSVC Express,我尝试编译和链接一个小型测试程序,并oci1.c针对.oci.hoci.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

关于 X86 调用约定的维基百科

在 Windows 上下文中为 x64 架构编译时(无论是使用 Microsoft 还是非 Microsoft 工具),只有一种调用约定 — 此处描述的一种,因此 stdcall、thiscall、cdecl、fastcall 等现在都是一个和相同的。

还与有关名称修饰的文章有关

现在对我来说很有意义。cdecl一个也是唯一的调用约定,因此不需要名称修饰,因此在为 X86 编译时没有前导下划线。

4

1 回答 1

1

我认为它只是在检查二进制兼容性之前抱怨缺少符号。这通常会首先发生,x64 符号没有前导下划线,因为 x64 没有任何调用约定。除非您使用 Microsoft 导入库,否则它们根本不会装饰符号。

但我非常同意,首先获得兼容性错误会更有效率。不知道实施起来有多难。询问知道并可以使其工作的人,向 connect.microsoft.com 发布功能请求

于 2011-10-29T12:54:57.047 回答