将DLL链接到Visual C++时未定义的外部链接

问题描述:

我从我想在C++ Visual Studio 2012项目中使用的供应商那里获得了一个dll。它带有一个.lib文件。将DLL链接到Visual C++时未定义的外部链接

链接时,我得到:

Error 1 error LNK2019: unresolved external symbol __imp__FT_CreateDeviceInfoList referenced in function "int __cdecl Ftexam(void)" ([email protected]@YAHXZ) C:\Users\Terry\Documents\Visual Studio 2012\Projects\Win32Project1\Win32Project1\ftexam.obj ftexample 

我读过类似的职位,但我没有得到任何地方。我想我正在根据这些答案做所有事情,但链接时仍然会出现未定义的参考错误。

  1. 我已将dll.lib文件添加到/ Linker/Addional Dependencies列表中。
  2. 我已经取得了一定的dll.h文件包含在我的源
  3. 我已经把dll.lib文件,在我的项目目录,并确保,如果我从那里删除它,我得到cannot find dll.lib链接时(即,它是 “在建”)

在我提供的dll.h头文件中我有这样的:

#ifdef DLL_EXPORTS 
#define DLL_API __declspec(dllexport) 
#else 
#define DLL_API __declspec(dllimport) 
#endif 
. 
. 
#ifdef __cplusplus 
extern "C" { 
#endif 

typedef ULONG FT_STATUS; 
. 
. 
DLL_API FT_STATUS FT_CreateDeviceInfoList(
    LPDWORD lpdwNumDevs 
); 

和我的调用代码是:

#include dll.h 

int Ftexam(){ 
    FT_STATUS ftStatus=0; 
    DWORD numDevs = 0; 

    // create the device information list 
    ftStatus = FT_CreateDeviceInfoList(&numDevs); 
} 

我意识到可能有一些名称正在发生变化,所以我使用depends来查看DLL符号。它列出了这些出口的“去除装饰C++功能”选项被禁用,(所以,这些都是未重整出口):

FT_Open 
FT_Close 
FT_Read 
.... 
FT_CyclePort 
FT_CreateDeviceInfoList< <<<<<this reference!!!! 
FT_GetDeviceInfoList 

标识的出口上面明显不符__imp__FT_CreateDeviceInfoList

是否有一个工具周围可以查看.lib文件中的定义,还是以某种方式让visual studio显示它?

UPDATE:

通过使用DUMPBIN的我能看到的.lib符号是

__imp_FT_CreateDeviceInfoList 

instead of 

__imp__FT_CreateDeviceInfoList 

这个我跟踪到的.lib为DLL的64位版本,而不是的32位版本。 (我试图首先解决这个问题的组合之一)。

为了简化后,我已表示,标头包含:

DLL_API FT_STATUS FT_CreateDeviceInfoList(LPDWORD lpdwNumDevs); 

When in fact, it actually contains: 

DLL_API FT_STATUS WINAPI FT_CreateDeviceInfoList(LPDWORD lpdwNumDevs); 

因为WINAPI被#define的

因此更改

#define WINAPI 
to 
#define WINAPI __stdcall 
与具有正确的.lib固定沿

问题。

+0

WINAPI应该已经被Windows正确定义。我承认你正在使用的图书馆,目前正在使用它,而无需修改。在包含库头之前,您是否“#include ”? –

FT_CreateDeviceInfoList()没有在.h文件中声明任何调用约定,所以它使用编译器的默认调用约定。您的编译器默认为__cdecl,这对于大多数C++编译器来说是正常行为。机会是,创建DLL的编译器实际上使用了不同的默认调用约定。尝试编辑.h文件到指定__stdcall,例如,看看它是否有什么差别,如:

DLL_API FT_STATUS __stdcall FT_CreateDeviceInfoList(LPDWORD lpdwNumDevs); 

大多数DLL供应商使用__stdcall为了兼容的编译器,而不是C/C++编译器的最广泛的选择,尽管一些供应商确实使用__cdecl甚至__fastcall(这是由不同的编译器供应商以不同的方式实现的,所以请注意这一点)。

更糟糕的情况是,您可以像IDA或WinDASM一样使用反汇编程序,或者只使用IDE自己的调试程序来查看DLL中的实际汇编代码FT_CreateDeviceInfoList(),并查看它在访问时如何管理调用堆栈lpdwNumDevs参数并返回FT_STATUS值。这将告诉你它究竟使用哪种调用约定。

UPDATE:做一些网上搜索,我看到应用于其声明调用FT_CreateDeviceInfoList()__stdcall调用约定的.NET代码例子很多,所以这是开始的好地方。如果有效,那么你应该联系DLL供应商,并要求他们相应地修复他们的.h文件。

+0

谢谢。通过使用dumpbin,我可以看到.lib中的符号是__imp_FT_CreateDeviceInfoList vs __imp__FT_CreateDeviceInfoList。我跟踪了这​​一点,以引用64位版本的.lib而不是32位版本。 – user1967890

你在做什么应该尽我所能地工作。但是你总是可以忘记.lib文件并直接使用该DLL,使用LoadLibrary加载它并获取要用于GetProcAddress的函数的地址。

打开Visual Studio命令提示符。火以下命令列出的符号在lib文件:

DUMPBIN /所有dll.lib

重定向以上到一个文本文件,作为输出滚出迅速