Предупреждение компоновщика «второе определение игнорируется» при включении двух библиотек с одинаковыми именами функций

контекст

Я работаю над проектом, предназначенным для отправки определенных команд на устройство. Каждое устройство может быть сопряжено с dll (например, deviceADll.h, deviceBDll.h), и я не запрограммировал dll, и я не могу изменять их каким-либо образом. Я отвечаю за интеграцию DeviceB в проект с минимальными изменениями в структуре проекта. Я знаю, что структура не может быть оптимальной и / или хорошо спроектированной, поэтому я готов принять предложение по этому вопросу в качестве последнего средства решения.

Поскольку устройства очень похожи, все функции Dll имеют одинаковое имя и часто один и тот же прототип.

Также из-за этого я создал родительский класс (Device_ts.h), от которого наследуются DeviceA_ts.h и DeviceB_ts.h (у меня также есть фабричный класс для устройств, но я не думаю, что он имеет отношение к моей проблеме) ,

проблема

Проблема возникает, когда я пытаюсь включить оба Dlls: проект компилируется, но я получаю

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_

2

Решение

Это хороший вариант использования для ручной загрузки DLL, используя LoadLibrary() а также GetProcAddress(),

Вам придется управлять указателем на функцию для каждой функции, которая выглядит таким образом, что немного болезненно, но обход загрузки 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;
}

Редактировать: По сути, я предлагаю вам рассматривать библиотеки устройств как плагины, а не как динамические библиотеки.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]