当包含两个具有相同功能名称的库时,链接器警告“忽略第二个定义”

时间:2017-08-18 19:58:06

标签: c++ visual-studio dll linker-warning

上下文

我正致力于一个旨在将某些命令发送到设备的项目。每个设备都可以与dll连接(例如deviceADll.h,deviceBDll.h),Dll不是由我编程的,也不能以任何方式修改它们。我负责将DeviceB集成到项目中,对项目结构的改动很小。我知道结构可能不是最佳和/或设计得很好,所以我愿意就此问题提出建议,作为最后的解决方案。

由于设备非常相似,所有Dll功能都具有相同的名称,并且通常是相同的原型。

也正因为如此,我创建了一个父类(Device_ts.h),DeviceA_ts.h和DeviceB_ts.h继承了它(我也有一个工厂的工厂类,但我不认为它与我的问题)。

问题

当我尝试包含两个Dll时出现问题:项目编译,但我得到了

Warning 60 warning LNK4006: Connect@12 already defined in DeviceA.lib(DeviceA.dll); second definition ignored C:\project_path\DeviceB.lib(DeviceB.dll) Project_Name

后跟

Warning 61 warning LNK4006: __imp__Connect@12 already defined in DeviceA.lib(DeviceA.dll); second definition ignored C:\project_path\DeviceB.lib(DeviceB.dll) Project_Name

Warning 62 warning LNK4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library C:\project_path\DeviceB.lib(DeviceB.dll) Project_Name

是否有人遇到类似情况?我是否应该忽略这些警告,否则我将无法调用DeviceB.h函数,因为他们的定义会被忽略?

我正在使用Visual Studio 2010,我正在编写的Device_ts.h库是一个静态库,并且所有项目的参数(例如/ MD,包括目录,依赖项,MFC等)都是根据我发现的正确设置的在我对这个问题的研究中。

代码

include和代码看起来像这样(我只会显示导致警告的一个函数,因为我在50个函数上得到了相同的错误):

DeviceADll.h

#ifndef DEVICEA_H__
#define DEVICEA_H__

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

namespace DeviceA
{
// some struct definition that don't cause the linker warnings
//...

// function definitions
extern "C" HANDLE PASCAL EXPORT Connect( HANDLE h_devA, const char *ip);
// ...
} // namespace DeviceA

DeviceBDll.h

#ifndef DEVICEB_H__
#define DEVICEB_H__

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

namespace DeviceB
{
// some struct definition that don't cause the linker warnings
//...

// function definitions
extern "C" HANDLE PASCAL EXPORT Connect( HANDLE h_devB, const char *ip);
// ...
} // namespace DeviceB

Device_ts.h

#ifndef DEVICE_FCT_H_
#define DEVICE_FCT_H_
#ifndef EXPORT
#define EXPORT
#endif

#if _MSC_VER > 1000
#pragma once
#endif

#include "DeviceADll.h"
#include "DeviceBDll.h"

class CDevice {
public:
    virtual BOOL Connect(char *ip_addr) = 0;
};
#endif DEVICE_FCT_H_

1 个答案:

答案 0 :(得分:3)

这是使用valueLoadLibrary()手动加载DLL的好用例。

你必须为这样查找的每个函数管理一个函数指针,这有点痛苦,但绕过操作系统的dll加载会给你很大的灵活性。

另请注意,使用此方法时不需要链接DLL,dll绑定是100%运行时,并且根本不涉及链接器。

以下是一个例子:

GetProcAddress()

编辑:基本上,我建议您将设备DLL视为插件,而不是动态库。