C ++ / CLI - .cpp源文件生成的.obj文件不包含符号(LNK2020)

时间:2014-07-11 14:41:33

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

目前,我正致力于在C ++ / CLI中为本地C库实现托管包装。

我没有这种语言的经验,本周在尝试完成我的项目时已成为一种速成课程。虽然它有一些令人惊讶的frustrating quirks,但仍然有很多好文章在附近。

背景:

  • 我在WrappedAvType中声明了一个类(Common.h),并且类成员在相应的Common.cpp中实现,它们都在项目根目录中。
  • 项目中的其他文件组织在各自的目录中,并包含..\Common.h以访问其包含的类声明
  • 环境:Windows 8.1 x64上的Visual Studio 2012,面向.NET Framework 4.5,生成x86二进制文件

COMMON.H:

#pragma once

namespace LibavDotNet {

    template<class T>
    public ref class WrappedAvType abstract
    {
    public:
        property bool IsDirty;
        WrappedAvType();
        WrappedAvType(T avObject);
        ~WrappedAvType();
        virtual T Unwrap();

    private:
        T _avObject;

    protected:
        virtual void SetAvObject(T avObject);
    };
}

Common.cpp:

#include "Common.h"

namespace LibavDotNet {

    template<class T>
    WrappedAvType<T>::WrappedAvType()
    {
        IsDirty = false;
    }

    template<class T>
    WrappedAvType<T>::WrappedAvType(T avObject)
    {
        _avObject = avObject;
    }

    template<class T>
    WrappedAvType<T>::~WrappedAvType()
    { }

    template<class T>
    T WrappedAvType<T>::Unwrap()
    {
        return _avObject;
    }

    template<class T>
    void WrappedAvType<T>::SetAvObject(T avObject)
    {
        _avObject = avObject;
    }
}

然而,我目前因为一个特殊的问题而感到难过(可能因为太长时间盯着代码而蒙羞...):每当我按照描述的状态编译项目时,我都会收到错误LNK2020表示找不到WrappedAvType的令牌。

为了确认符号在生成的二进制文件中是否可用,我使用了dumpbin /symbols Common.obj,实际上并不是任何符号:

Microsoft (R) COFF/PE Dumper Version 11.00.61030.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file Common.obj

File Type: COFF OBJECT

COFF SYMBOL TABLE
000 00CFEE66 ABS    notype       Static       | @comp.id
001 80000191 ABS    notype       Static       | @feat.00
002 00000000 SECT1  notype       Static       | .drectve
    Section length   78, #relocs    0, #linenums    0, checksum        0
004 00000000 SECT2  notype       Static       | .debug$S
    Section length  35C, #relocs    0, #linenums    0, checksum        0
006 00000000 SECT3  notype       Static       | .debug$T
    Section length   7C, #relocs    0, #linenums    0, checksum        0
008 00000000 SECT4  notype       Static       | .cormeta
    Section length  45C, #relocs    0, #linenums    0, checksum        0

String Table Size = 0x0 bytes

  Summary

         45C .cormeta
         35C .debug$S
          7C .debug$T
          78 .drectve

如果我将类实现直接与#include "..\Common.cpp"一起包含在需要它的其他源文件中(到目前为止只有一个),那么项目将按预期编译。 在这一点上,我不知道还有什么可以尝试并且已经搜索了几个小时的解决方案。我非常希望将我的标题与类声明和源文件保持分开。

我完全相信这是一个我忽略的小事,或者我太绿了,无法注意到。我错过了什么?

1 个答案:

答案 0 :(得分:2)

template<class T>

这是一个标准的C ++问题,它与C ++ / CLI没有任何关系。模板没有外部链接。模板类的整个实现必须存在于.h文件中。这就是#include工作的原因。

请记住强大的代码味道,模板是纯C ++功能。您的包装器实际上并不可用于任何其他.NET语言,当然它们不支持模板。只有使用泛型关键字声明的ref类才可用。