Ошибка компоновки только для одной функции. Другие функции с аналогичной сигнатурой в том же классе и файле CPP работают нормально.

Подобный вопрос для этого типа ошибки связи задавался ранее, и я изучил большинство (если не все) из них. Некоторые похожие вопросы здесь, GitHub и MSDN, которые я изучил, чтобы решить эту проблему:

Github:

MSDN:

StackOverflow 1

StackOverflow 2

Stackoverflow 3

Stackoverflow 4

Stackoverflow 5

Проблема. У меня есть устаревший продукт с более чем 400+ проектами Visual Studio в 4 файлах Visual Studio Solution. Я столкнулся с проблемой с проектом, который является COM-компонентом, он должен использовать dll (который содержит статические функции), созданный из другого проекта; все статические функции из dll работают нормально, кроме одной, которую я пытаюсь в нее добавить. Проект, который создает dll, строится нормально без каких-либо ошибок, файлы header и cpp, содержащие статические функции, выглядят следующим образом.

файл: InvocationInterface.h

using namespace some_namespace;

#ifdef _WIN64
#pragma pack(8)
#else
#pragma pack(1) // tag for search
#endif

typedef struct 
{

    long nDBMS;
    long nDBMSVersion;
    long nDBMSMinorVersion;
    LPSTR szCaption; 
    LPSTR szRepGroupName;
    std::vector<bool> xDBMSOptions;
    EouGdmIdList selectedEntityIds;
    BOOL bIsAlterScript;
    int nInvoke;
    LPSTR szConnectionInfo;
    LPSTR szPassword;
    LPSTR szOptionXML;
    LPSTR szDDLPath;
} EouFEPARAM;

class EOU_EXPORT CUIInvocationInterface
{ 
public:
    CUIInvocationInterface(void);
    ~CUIInvocationInterface(void);

    // A lot of other similar static functions
    static void SetIncludeSysTablesForRevEng(GDMModelSetI* pxModelSet,BOOL bShow);

    static void setNSMCSV(GDMModelSetI* pxModelSet, CString csPath, bool append);

};
#pragma pack( pop, EouUIInvocationInterface_H_pack )

Файл InvocationInterface.cpp:

#include "Header_files"

//Constructor
CUIInvocationInterface::CUIInvocationInterface(void)
{
}
//Destructor
CUIInvocationInterface::~CUIInvocationInterface(void)
{
}

// Old legacy code working just fine if I remove the function that is casusing linking error
void SetIncludeSysTablesForRevEng(GDMModelSetI* pxModelSet, BOOL bShow)
{
    return SetIncludeSysTables(pxModelSet, bShow);
}

// Function that is causing Linking Error
void setNSMCSV(GDMModelSetI* pModelSet, CString & sFilePath, bool bAppend)
{
    CWnd * wnd = nullptr;
    EouRESetOptions ForRE(wnd);
    ForRE.ProcessCSV(sFilePath, true);
}

Компонент COM, который использует эти функции, использует их следующим образом: ComProxyFile.cpp

bool function(formal_parameters, ...)
{


    ...
    ...

    CUIInvocationInterface::setNSMCSV(pxModelSet, strCSVpath, true);
    CUIInvocationInterface::SetIncludeSysTablesForRevEng(pxModelSet, bIncludeSystemTables);

    ...
    ...



    SOMECLASS::OnInvokeAFunction(args, ...);
    return bRet;
}

Функция setNSMCSV вызывает ошибку LNK2019, когда я создаю компонент COM, использующий dll, существует 20+ таких статических функций, объявленных и определенных аналогичным образом, но все они работают нормально, кроме setNSMCSV, которые я пытаюсь реализовать. Если я создам проект, использующий эти функции, он выдаст следующую ошибку: error LNK2019: unresolved external symbol "__declspec(dllimport) public: static void __cdecl CUIInvocationInterface::setNSMCSV(class GDMModelSetI *,class ATL::CStringT<char,class StrTraitMFC_DLL<char,class ATL::ChTraitsCRT<char> > >,bool)"

Если я закомментирую строку CUIInvocationInterface::setNSMCSV(pxModelSet, strCSVpath, true);, то она отлично скомпилируется.

Я попытался дать setNSMCSV определение функции __declspec(dllexport) __cdecl, extern "C" и использовать pragma comment, добавив .lib к компоненту COM, который использует функции, и другие вещи, которые я смог найти, которые были предложены в других подобных вопросах здесь.

Почему эта единственная функция вызывает эту проблему? Другие функции имеют такие же сигнатуры и аналогичную реализацию, но работают нормально.


person Abhishek    schedule 22.03.2018    source источник


Ответы (2)


В InvocationInterface.cpp вам нужно изменить определение функции, чтобы включить имя класса, т.е. из:

void setNSMCSV(GDMModelSetI* pModelSet, CString & sFilePath, bool bAppend)
{
    CWnd * wnd = nullptr;
    EouRESetOptions ForRE(wnd);
    ForRE.ProcessCSV(sFilePath, true);
}

to:

void CUIInvocationInterface::setNSMCSV(GDMModelSetI* pModelSet, CString & sFilePath, bool bAppend)
{
    CWnd * wnd = nullptr;
    EouRESetOptions ForRE(wnd);
    ForRE.ProcessCSV(sFilePath, true);
}
person Liam Finnie    schedule 22.03.2018
comment
Я с этого и начал. У меня выдает ошибку error C2511: 'void CUIInvocationInterface::setNSMCSV(GDMModelSetI *,CString &,bool)' : overloaded member function not found in 'CUIInvocationInterface' - person Abhishek; 22.03.2018
comment
А, у вас была другая проблема, в определении есть ссылка на второй параметр, но в объявлении нет ссылки. Либо используйте CStringдля обоих, либо используйте CString& для обоих. - person Liam Finnie; 22.03.2018
comment
Ох черт!! Я такой тупой. Я не могу в это поверить. Спасибо, что указали на это. Думаю, я ослепну или что-то в этом роде. Большое спасибо. - person Abhishek; 22.03.2018

Замените void setNSMCSV(GDMModelSetI* pModelSet, CString & sFilePath, bool bAppend) на void CUIInvocationInterface::setNSMCSV(GDMModelSetI* pModelSet, CString & sFilePath, bool bAppend) в файле .cpp. Вы объявили ее как статическую функцию класса, но определили ее как свободную функцию (а не как член класса).

Ваш заголовок:

class EOU_EXPORT CUIInvocationInterface
{ 
public:
    CUIInvocationInterface(void);
    ~CUIInvocationInterface(void);

    // A lot of other similar static functions
    static void SetIncludeSysTablesForRevEng(GDMModelSetI* pxModelSet,BOOL bShow);

    static void setNSMCSV(GDMModelSetI* pxModelSet, CString csPath, bool append); // <-- Static class member function

};

Ваша цена за тысячу показов:

// Function that is causing Linking Error
void setNSMCSV(GDMModelSetI* pModelSet, CString & sFilePath, bool bAppend) //<-- not a member function
{
    CWnd * wnd = nullptr;
    EouRESetOptions ForRE(wnd);
    ForRE.ProcessCSV(sFilePath, true);
}
person Rudolfs Bundulis    schedule 22.03.2018
comment
На самом деле я начал с этого, что дает мне ошибку: error C2511: 'void CUIInvocationInterface::setNSMCSV(GDMModelSetI *,CString &,bool)' : overloaded member function not found in 'CUIInvocationInterface' - person Abhishek; 22.03.2018