簡體   English   中英

當包含兩個具有相同功能名稱的庫時,鏈接器警告“忽略第二個定義”

[英]Linker warning “second definition ignored” when including two libraries with same function names

上下文

我正在開發一個旨在將某些命令發送到設備的項目。 每個設備都可以與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

和a

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_

這是使用LoadLibrary()GetProcAddress()進行手動DLL加載的一個很好的用例。

你必須為這樣查找的每個函數管理一個函數指針,這有點痛苦,但是繞過操作系統的dll加載會給你很大的靈活性。

另請注意,使用此方法時不需要鏈接DLL,dll綁定是100%運行時,並且根本不涉及鏈接器。

這是一個例子:

typedef void (*connect_fn)(HANDLE, const char*);

connect_fn connect_a;
connect_fn connect_b;

int main()
{
  HINSTANCE dll_a = LoadLibrary("path_to_dll_a.dll");
  HINSTANCE dll_b = LoadLibrary("path_to_dll_b.dll");

  if (!dll_a || !dll_b) {
    return 1;
  }

  connect_a = (connect_fn)GetProcAddress(dll_a , "Connect");
  connect_b = (connect_fn)GetProcAddress(dll_b , "Connect");

  // connect_a and connect_b can now be used.
  return 0;
}

編輯:基本上,我建議你將設備DLL視為插件,而不是動態庫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM