从纯C ++代码调用C ++ / CLI代码时链接器错误

时间:2014-03-29 11:03:56

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

我正在使用VS2012,我正在尝试从C ++调用CLI代码。所以我创建了两个项目。一个是可执行文件,它是纯C ++(没有CLI支持),第二个是动态库,它是CLI(带有/ clr开关)。如果我有main(可执行文件):

// main.cpp file
#include "..\CLILibrary\CCli.h"

int main()
{
    Ccli test = Ccli();
    test.Write();
    return 0;
}

CLI库中的一个类(使用CLR开启构建):

// Ccli.h file
#pragma once

class Ccli
{
public:
    void Write();
    void CallRealCLIClass();
};

// Ccli.cpp file
#include " Ccli.h"

void Ccli::Write()
{
    System::Console::WriteLine("In Ccli class.");
}

void Ccli::CallRealCLIClass()
{
    // here I would like to call RealCLI class
}

到目前为止一切正常。据我所知,该头文件(Ccli.h)不能使用CLI中的任何内容,因为它必须对我的可执行文件是可读的,这纯粹是用C ++编写的(理论上如果我使用像#ifdef _MANAGED这样的东西,但这不是我的意思)。但在源文件(Ccli.cpp)中它很好。

但是现在我想使用完全CLI的类。我想从Ccli.cpp文件中调用它。所以我在CLI库中创建了以下类:

// RealCLI.h file
#pragma once
ref class RealCLI
{
public:
    RealCLI(void);
    System::String^ GetString();
    void Write(System::String^ s);
};
// RealCLI.cpp file
#include "RealCLI.h"

RealCLI::RealCLI(void){}

System::String^ GetString()
{
    System::String^ s = gcnew System::String("GetString in RealCLI class");
    return s;
}

void Write(System::String^ s)
{
    System::Console::WriteLine(s);
}

现在我有以下问题,我不知道为什么。我从链接器收到此错误:

错误1错误LNK2020:未解析的令牌(06000002)RealCLI :: GetString ... \ RealCLI \ RealCLI.obj

错误2错误LNK2020:未解析的令牌(06000003)RealCLI :: Write ... \ RealCLI \ RealCLI.obj

错误3错误LNK1120:2个未解析的外部... \ Debug \ RealCLI.dll 1

所以我的库很好(它构建没有问题)但我的可执行文件有这些链接器错误。我不明白为什么?我不在我的可执行项目中使用此文件,为什么我的可执行文件甚至关心它?我找到了解决方法。但由于我不知道为什么原始程序不起作用,我认为它只是解决方法。我的解决方法是删除RealCLI.cpp文件并将所有内容放在头文件中:

// RealCLI.h file
#pragma once

ref class RealCLI
{
public:
    RealCLI(void) {}

    // I cannot even put definition outside declaration of my class
    System::String^ GetString()
    {
        System::String^ s = gcnew System::String("GetString in RealCLI class");
        return s;
    }

    void Write(System::String^ s)
    {
        System::Console::WriteLine(s);
    }
};

为什么?我究竟做错了什么?我的一些假设是错的吗?

修改

// Ccli.cpp file
#include " Ccli.h"
// !!!added this line:
#include "RealCLI.h"

void Ccli::Write()
{
    System::Console::WriteLine("In Ccli class.");
}

void Ccli::CallRealCLIClass()
{
    // here I would like to call RealCLI class
}

我在RealCli.cpp中修复了名称空间,这有帮助。但是当我添加#include“RealCLI.h”时,无论如何我都会遇到这些错误:

错误2错误LNK2020:未解析的令牌(06000001)RealCLI ::。ctor D:\ ftp \ my \ vyuka-cppToCLI-test \ vyuka-ManagedUmanaged \ UnmanagedToManagedSource.obj

错误3错误LNK2020:未解析的令牌(06000002)RealCLI :: GetString D:\ ftp \ my \ vyuka-cppToCLI-test \ vyuka-ManagedUmanaged \ UnmanagedToManagedSource.obj

错误4错误LNK2020:未解析的令牌(06000003)RealCLI ::写入D:\ ftp \ my \ vyuka-cppToCLI-test \ vyuka-ManagedUmanaged \ UnmanagedToManagedSource.obj

错误5错误LNK1120:3个未解析的外部D:\ ftp \ my \ vyuka-cppToCLI-test \ Debug \ vyuka-ManagedUmanaged.exe 1

2 个答案:

答案 0 :(得分:1)

你犯了基本的C ++错误。在RealCLI.cpp中:

而不是:

System::String^ GetString() { ... }

使用:

System::String^ RealCLI::GetString() { ... }

同样适用于Write()

答案 1 :(得分:0)

实际上我没有设置链接器。代码是(编辑后)确定。我链接到.obj文件,因为直接链接到.dll时出错(因为它不是纯C ++而是CLI)。我只链接了Ccli.obj然后几周后我添加了另一个文件并忘记链接RealCLI.obj ...