LNK2020: неразрешенный токен (06000001) и LNK4248: неразрешенный токен типа (0100001E) - PullRequest
0 голосов
/ 29 февраля 2020

Я написал слой-обертку в Managed C ++, который взаимодействует с уровнем API для стороннего программного обеспечения, написанного на Native C ++. Теперь обертка компилируется и собирается корректно. Порядок компоновки выглядит следующим образом: (1) сторонний API (Native C ++ и собран как библиотека), (2) мой уровень Warpper в Managed C ++ (C ++ / CLR и собран как библиотека), (3) написано основное приложение в Managed C ++ с использованием моей оболочки для взаимодействия со сторонним API.

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

namespace RvBeehdClientApiWrapper
{
public ref class BeehdClientInitParamsWapper : public IBeehdClientInitParamsWapper
{
public:
    BeehdClientInitParamsWapper();

    ~BeehdClientInitParamsWapper();

    ///*virtual*/ bool get_VideoOutHwnd(unsigned long long^ newVal) { return true; };
    virtual bool put_VideoOutHwnd(unsigned long long newVal);

    ///*virtual*/ bool get_VideoLocalOutHwnd(unsigned long long^ newVal) { return true; };
    virtual bool put_VideoLocalOutHwnd(unsigned long long  newVal);

    ///*virtual*/ bool get_VideoOutPncHwnd(unsigned long long^ pVal) { return true; };
    virtual bool put_VideoOutPncHwnd(unsigned long long newVal);

    ///*virtual*/ bool get_ConfigFilePath(String^ pVal) { return true; };
    virtual bool put_ConfigFilePath(String^ newVal);

    ///*virtual*/ bool get_ProgramDataPath(String^ pVal) { return true; };
    virtual bool put_ProgramDataPath(String^ newVal);

    ///*virtual*/ bool get_LogFilesNumber(unsigned long^ pVal)  { return true; };
    virtual bool put_LogFilesNumber(unsigned long newVal);

    ///*virtual*/ bool get_LogFilesSize(unsigned long^ pVal)  { return true; };
    virtual bool put_LogFilesSize(unsigned long newVal);

    ///*virtual*/ bool get_LogsPath(String^ pVal) { return true; };
    virtual bool put_LogsPath(String^ newVal);

    ///*virtual*/ bool get_LicenseFilePath(String^ pVal) { return true; };
    virtual bool put_LicenseFilePath(String^ newVal);

    ///*virtual*/ bool get_IotFilePath(String^ pVal) { return true; };
    virtual bool put_IotFilePath(String^ newVal);

    virtual bool put_HistoryFilePath(String^ newVal);

    virtual bool put_IsAppLogEnabled(bool newVal);

    virtual bool put_IsLogContinuityOnStart(bool newVal);

    const CBeehdClientInitParamsImpl* get_InitializationParams() { return m_InitializationParams; }


private:
    CBeehdClientInitParamsImpl*          m_InitializationParams;

};
}

И его интерфейсный класс выглядит следующим образом:

namespace RvBeehdClientApiWrapper
{
public interface class IBeehdClientInitParamsWapper
{
    bool put_VideoOutHwnd(unsigned long long newVal);
    bool put_VideoLocalOutHwnd(unsigned long long  newVal);
    bool put_VideoOutPncHwnd(unsigned long long newVal);
    //bool get_ConfigFilePath(String^ pVal);
    bool put_ConfigFilePath(String^ newVal);
    //bool get_ProgramDataPath(String^ pVal);
    bool put_ProgramDataPath(String^ newVal);
    //bool get_LogFilesNumber(unsigned long^ pVal);
    bool put_LogFilesNumber(unsigned long newVal);
    //bool get_LogFilesSize(unsigned long^ pVal);
    bool put_LogFilesSize(unsigned long newVal);
    //bool get_LogsPath(String^ pVal);
    bool put_LogsPath(String^ newVal);
    //bool get_LicenseFilePath(String^ pVal);
    bool put_LicenseFilePath(String^ newVal);
    //bool get_IotFilePath(String^ pVal);
    bool put_IotFilePath(String^ newVal);
    bool put_HistoryFilePath(String^ newVal);
    bool put_IsAppLogEnabled(bool newVal);
    bool put_IsLogContinuityOnStart(bool newVal);
};
}

Основной прикладной уровень использует BeehdClientInitParamsWapper через класс Factory. Задача фабричного класса - создать одноэлементный экземпляр класса BeehdClientInitParamsWapper и вернуть экземпляр, чтобы его можно было использовать для доступа к открытым методам, предоставляемым классом IBeehdClientInitParamsWapper. Ниже приведена реализация класса Factory для BeehdClientInitParamsWapper:

#pragma once
 #include "IApiWrapperClass.h"

 using namespace System;

namespace RvBeehdClientApiWrapper
{
ref class ApiWrapperClass;

public interface class IApiWrapperFactory
{
    IApiWrapperClass^ GetWrapperApiInstance();
};

public ref class ApiWrapperFactory : public IApiWrapperFactory
{
public:
    ApiWrapperFactory() {}
    ~ApiWrapperFactory() {}

    virtual IApiWrapperClass^ GetWrapperApiInstance();

private:

    static ApiWrapperClass^  m_theWrapperInstance;
};
}

Тело класса фабрики выглядит следующим образом:

   #include "ApiWrapperFactory.h"
   #include "RvBeehdClientApiWrapper.h"


   RvBeehdClientApiWrapper::IApiWrapperClass^   RvBeehdClientApiWrapper::ApiWrapperFactory::GetWrapperApiInstance()
   {
     if (m_theWrapperInstance == nullptr)
     {
        m_theWrapperInstance = gcnew ApiWrapperClass();
     }
     return m_theWrapperInstance;
   }

Основной уровень приложения (3 выше) использует следующие методы:

#include "BeehdClientInitParamsFactory.h"
#include "IBeehdClientInitParamsWapper.h"

bool RifMCDllMain::Start(...)
{
bool success = true;

try
{
    // Store the passed in RCA Config data reference.
    CConfigDetails ^ config = CConfigDetails::Instance;
    config->UseRcaConfig(rcaConfig);

    if (config->ReadConfigData())
    {
        // 1. Call Wrapper to populate the parameter object.
        RvBeehdClientApiWrapper::BeehdClientInitParamsFactory^ _ptrWrapperParamFactory = 
            gcnew RvBeehdClientApiWrapper::BeehdClientInitParamsFactory();
        RvBeehdClientApiWrapper::IBeehdClientInitParamsWapper^ _pwrapperparameters =
            _ptrWrapperParamFactory->get_WrapperInitParamsInstance();

        //Populate the parameter object.
        _pwrapperparameters->put_VideoOutHwnd(5049174);
        _pwrapperparameters->put_VideoLocalOutHwnd(992466);
        _pwrapperparameters->put_VideoOutPncHwnd(468162);
        ...
    }
    else
    {
        _log->Error("Read RIF config data failed");
        success = false;
    }

После того, как все это реализовано, я компилирую решение в следующем порядке: (i) Сторонний API (Native C ++ и собран как библиотека) -> Компилируется и создает библиотеку (ii) Мой слой-обертка в Managed C ++ (C ++ / CLR и построен как библиотека) -> Это компилирует и создает мою библиотеку-обертку (iii) Основное приложение, написанное на Managed C ++ использование моей обертки для связи со сторонним API -> Это приводит к следующей ошибке связи:

Ошибка компиляции

Ошибка компиляции

Пожалуйста, сообщите, потому что я действительно застрял. Заранее большое спасибо.

Пожалуйста, просмотрите ошибку компиляции ниже:

1>------ Build started: Project: RifMC, Configuration: Debug Win32 ------
1>ConfigurationDetails.obj : /DEBUG:FASTLINK is not supported when managed code is present; restarting link with /DEBUG:FULL
1>ConfigurationDetails.obj : MSIL module encountered; incremental linking is disabled for MSIL; performing full link
1>RifMCDllMain.obj : warning LNK4248: unresolved typeref token (0100001E) for 'RvBeehdClientApiWrapper.ApiWrapperClass'; image may not run
1>RifMCDllMain.obj : warning LNK4248: unresolved typeref token (0100001F) for 'RvBeehdClientApiWrapper.BeehdClientInitParamsWapper'; image may not run
1>RifMCDllMain.obj : error LNK2020: unresolved token (06000069) RvBeehdClientApiWrapper.ApiWrapperFactory::GetWrapperApiInstance
1>RifMCDllMain.obj : error LNK2020: unresolved token (06000070) RvBeehdClientApiWrapper.BeehdClientInitParamsFactory::get_WrapperInitParamsInstance
1>C:\Git\DSxMissionCriticals\DSxSuper\MissionCritical\RifMC\Debug\RifMC.dll : fatal error LNK1120: 2 unresolved externals
1>Done building project "RifMC.vcxproj" -- FAILED.

========== Сборка: 0 успешно завершено, 1 не удалось , 0 актуально, 0 пропущено ==========

======================= =================================================

namespace RvBeehdClientApiWrapper
{
ref class BeehdClientInitParamsWapper;

public interface class IBeehdClientInitParamsWapperFactory
{
    RvBeehdClientApiWrapper::IBeehdClientInitParamsWapper^ get_WrapperInitParamsInstance();
};

public ref class BeehdClientInitParamsFactory : public IBeehdClientInitParamsWapperFactory
{
public:
    BeehdClientInitParamsFactory() {}

    ~BeehdClientInitParamsFactory() {}

    virtual RvBeehdClientApiWrapper::IBeehdClientInitParamsWapper^ get_WrapperInitParamsInstance();

private:
    static BeehdClientInitParamsWapper^  m_theWrapperInitParamInstance;
};
}

Тело показано ниже:

RvBeehdClientApiWrapper::IBeehdClientInitParamsWapper^ RvBeehdClientApiWrapper::BeehdClientInitParamsFactory::get_WrapperInitParamsInstance()
{
   if (m_theWrapperInitParamInstance == nullptr)
   {
       m_theWrapperInitParamInstance = gcnew  RvBeehdClientApiWrapper::BeehdClientInitParamsWapper();
   }
   return m_theWrapperInitParamInstance;
}
...