【问题标题】:Visual C++/CLI - CLR Class - LNK2020 Error - how to fix?Visual C++/CLI - CLR 类 - LNK2020 错误 - 如何修复?
【发布时间】:2011-03-08 22:46:22
【问题描述】:

我有一个项目,我必须连接到基于 C 的库,但我无法使用 DLLImport 从 C# 获取函数。我必须使用基于 C++/CLI 的项目来展示这些功能以供使用。 (更多关于那个故事,但并不重要)。

我在 10 多年前学习 C++,如果这看起来很幼稚,请原谅我。
去年我购买了几本关于 C++/CLI 实现的书籍,并且对所涉及的内容有所了解——我只为这个项目深入研究了这些书籍。 (我做程序员很久了)。

我想我最好开始一个小项目示例项目,以熟悉将涉及的内容,以确保我可以编译等。我使用 Visual Studio 2008 SP1 开始了一个项目; Visual C++ > CLR > 类库。在项目中 - 我想同时使用 DLL 中的托管和本机。所以使用了 /clr 开关。

我在实际代码中使用了其他名称;但这非常非常接近。 (此时没有其他文件或函数)

标题:

//myWrapper.h
#pragma once
using namespace System;
namespace myWrapper {
  public ref class myWrappedService {
         myWrappedService();
         bool Connected(String ^user,String ^password,String ^domain);
  }
};

并且实现有这个。

//myWrapper.cpp
//This is the main DLL file
#include "stdafx.h"
#include "myWrapper.h"
using namespace System;
public ref class myWrappedService
   {
      public:
            myWrappedService() {}
            bool Connected(String ^user,String ^password,String ^domain)
            {
               //just a simple result to start - no real functionality
               bool result = false;
               return result;
            }
   };

那是代码 - 编译但得到链接器错误。

错误 LNK2020:未解析的令牌 (06000002) myWrapper.myWrappedService::Connected

致命错误 LNK1120:1 个未解决的外部错误。

这看起来很简单——我可能会从 C# 方法中思考很多。我希望这很简单——但我不熟悉我应该在 CLI 方法中看到的内容。 (我花了几个小时寻找答案,最后觉得我需要发布一个可能会得到答案的问题。

【问题讨论】:

    标签: visual-c++ linker c++-cli


    【解决方案1】:
    namespace myWrapper {
    

    从那里开始出错了。您的 .h 文件在该命名空间内声明了一个类,其名称为 myWrapper::myWrappedService。您的 .cpp 文件声明了不在命名空间中的 另一个 类,它的名称是 ::myWrappedService。不同的名字,编译器不会抱怨看到同一个类被定义了两次。第一个类没有实现 Connected 方法,这就是链接器抱怨的原因。

    sad_man 的 sn-ps 也有同样的缺陷。第一个 sn-p 定义 ::myWrappedService::Connected() 方法。错误的命名空间。第二个sn-p和你有同样的缺陷。

    当您在托管代码中编写类库时,您不需要 .h 文件。程序集中的元数据起着同样的作用,它包含程序集中类型的声明。您的项目中没有其他需要类声明的 .cpp 文件,不需要 .h。因此,只需将所有内容写入 .cpp 文件即可:

    #include "stdafx.h"
    // Note: header file removed
    
    using namespace System;
    
    namespace myWrapper {
    
        public ref class myWrappedService
        {
        public:
            myWrappedService() {}
            void Connect(String ^user, String ^password, String ^domain)
            {
                throw gcnew NotImplementedException;
            }
        };
    }
    

    【讨论】:

    • 我尝试了您的方法 - Connect 行抱怨错误 3149:如果没有顶级 '^','System::String' 无法在此处使用此类型。我还需要一个返回值来说明我已连接 - 如果你可以修改你的示例 - 可能会起作用。
    • 我在发布之前验证了此代码已编译并内置到工作程序集中。 Connect() 的字符串参数在 sn-p 中显然有一个可见的 ^,请验证它的副本。我认为您可以自己弄清楚如何更改方法的返回类型。
    • 我的错误 - 错字 - 并使用我的返回类型编译。当我用反射器打开 DLL 时,方法就在那里。谢谢。
    【解决方案2】:

    你的 cpp 文件全错了。要使用 cpp 头文件,请查看 herehere。 C++/Cli 具有相同的头文件和 cpp 文件概念。实际上,您的 cpp 文件应该是头文件。

    你也可以这样:

    //myWrapper.h
    #pragma once
    #include "stdafx.h"
    using namespace System;
    namespace myWrapper {
      public ref class myWrappedService {
             myWrappedService();
             bool Connected(String ^user,String ^password,String ^domain);
      }
    };
    
    //myWrapper.cpp
    //This is the main DLL file
    #include "stdafx.h"
    #include "myWrapper.h"
    using namespace System;
    namespace myWrapper
    {
      myWrappedService::myWrappedService() {}
      bool myWrappedService::Connected(String ^user,String ^password,String ^domain)
      {
          bool result = false;
          return result;
      }
    } 
    

    或者像这样(你的案例一个标题):

    //myWrapper.h
    //This is the main DLL file
    #include "myWrapper.h"
    using namespace System;
    namespace myWrapper
    {
    public ref class myWrappedService
       {
          public:
                myWrappedService() {}
                bool Connected(String ^user,String ^password,String ^domain)
                {
                   //just a simple result to start - no real functionality
                   bool result = false;
                   return result;
                }
       };
    }
       // Remember? this was your cpp.
    

    编辑:我忘记了命名空间。但我认为你应该了解什么是头文件和 cpp 文件。

    【讨论】:

    • 我尝试了您的第一个示例 - 在具有实际名称的代码库上 - 没有工作。然后我使用这些示例名称创建了一个新项目 - 相同的问题(甚至不是编译)。我认为您试图指出标头和实现之间的区别。
    • 然后我尝试了您的“仅标头”方法 - 它可以编译和链接 - 但是将反射器指向 DLL 表明该方法永远不会出现。
    猜你喜欢
    • 2011-04-25
    • 2017-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-22
    • 1970-01-01
    • 2012-12-17
    相关资源
    最近更新 更多