【问题标题】:Adding a native class to a managed project将本机类添加到托管项目
【发布时间】:2017-04-13 15:58:35
【问题描述】:

这可能只是我缺乏 c++/cli 知识造成的,但我似乎在任何地方都找不到这个问题。

我有一个名为 ManagedProject 的项目,它使用 /CLR 编译,并有一个 (c++/cli) ref 类,名为 RefClass.cpp,以及一个原生 C++ 类,名为 CppClass.cpp。

我可以从 RefClass 调用 CppClass 的构造函数。

但是,我无法从也使用 /clr 编译的单独项目“OtherProject”中调用 CppClass。 OtherProject 只有 Other.cpp。 OtherProject 具有对 ManagedProject 的引用,因此我可以调用 RefClass,但即使我能够 #include "CppClass.h",当我尝试调用 CppClass 的构造函数时,也会出现 LNK2019 和 LNK2028 错误。

从非/clr 本机类调用它时,我遇到了同样的错误。


这是一个代码示例:

托管项目

RefClass.cpp:

// has a .h file with the constructor declaration & instance variable int test;
#include "CppClass.cpp"
RefClass:RefClass(int test){
    this->test = test;
    CppClass inst(42); //This works
}

CppClass.cpp:

// has a .h file with the constructor declaration & instance variable int test2;
CppClass:CppClass(int test2){
    this->test2 = test2;
}

其他项目

其他.cpp:

#include "CppClass.cpp"
int wmain(/*args*/){
    RefClass^ refinst = gcnew RefClass(64); //This works    
    CppClass inst(42); //This fails, I get LNK2019 & LNK2028 at Other.obj
}

实际错误输出: 注意:这里的SQLPrecheckReport是CppClass,appzsqlmigrate.cpp是Other.cpp,appzsqlmigrate是OtherProject的名字。

32>appzsqlmigrate.obj:错误 LNK2028:未解析的令牌 (0A000B59) “公共:__cdecl SQLPrecheckReport::SQLPrecheckReport(int)” (??0SQLPrecheckReport@@$$FQEAA@H@Z) 在函数“int”中引用 __cdecl wmain(int,wchar_t * * const)" (?wmain@@$$HYAHHQEAPEA_W@Z)

32>appzsqlmigrate.obj:错误 LNK2028:未解析的令牌 (0A000B5A) “公共:__cdecl SQLPrecheckReport::~SQLPrecheckReport(void)” (??1SQLPrecheckReport@@$$FQEAA@XZ) 在函数“int __cdecl”中引用 wmain(int,wchar_t * * const)" (?wmain@@$$HYAHHQEAPEA_W@Z)

32>appzsqlmigrate.obj:错误 LNK2019:未解析的外部符号 “公共:__cdecl SQLPrecheckReport::SQLPrecheckReport(int)” (??0SQLPrecheckReport@@$$FQEAA@H@Z) 在函数“int”中引用 __cdecl wmain(int,wchar_t * * const)" (?wmain@@$$HYAHHQEAPEA_W@Z)

32>appzsqlmigrate.obj:错误 LNK2019:未解析的外部符号 “公共:__cdecl SQLPrecheckReport::~SQLPrecheckReport(void)” (??1SQLPrecheckReport@@$$FQEAA@XZ) 在函数“int __cdecl”中引用 wmain(int,wchar_t * * const)" (?wmain@@$$HYAHHQEAPEA_W@Z)

【问题讨论】:

  • CLR 为模块提供了出色的支持,但它也不会追溯性地将这种支持添加到非托管代码中。你必须在这里做正常的 C++ 舞蹈,将 C++ 类放在一个普通的静态库或 DLL 项目中,并链接它们的 .lib,以便可以共享本机代码。
  • @HansPassant ,我现在看到这个问题与 c++/cli 无关。抱歉,如果这看起来很明显,我对使用 dll 和库完全陌生。你能给我指示这样做:“将 C++ 类放在一个普通的静态库或 DLL 项目中并链接它们的 .lib,以便可以共享本机代码”?到目前为止我所尝试的并没有解决错误......

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


【解决方案1】:

C++/CLI 允许托管和非托管代码一起存在于同一个 DLL 中,但它们仍然使用它们通常使用的链接机制。

通过将托管类标记为公共并将程序集加载为引用来链接托管代码。非托管代码通过在导出 DLL 中指定 __declspec(dllexport) 和在导入 DLL/EXE 中指定 __declspec(dllimport) 导出函数来链接。

如果您想将其导出为 C++ 类,则需要 #include "CppClass.h",根据您的错误消息,您似乎已经在这样做了。您需要指定那些 declspec 属性;通常的方法是在项目设置中为 ManagedProject 定义一个预处理器符号,而不是为 OtherProject 定义一个预处理器符号,然后将其关闭以#define 为__declspec(dllexport)__declspec(dllimport)

另一种方法是将非托管类包装在托管类中,并使用 .Net 机制来处理链接。这将使链接更简单,这正是 C++/CLI 的设计目的(尽管通常包装器会被 C# 使用,而不是更多的 C++/CLI)。

【讨论】:

  • 嗨,大卫,感谢您的帮助。我不熟悉如何使用 dll(我还是 c++ 和托管 c++ 的新手)。我该如何执行此步骤:“在 ManagedProject 的项目设置中定义了预处理器符号”?理想情况下,我想使用 CppClass 作为 RefClass 的包装器,这样我就可以使用非托管项目中的 RefClass。推荐的方法是什么?
  • 啊,你走的是另一条路。我自己没有这样做,但我的理解是您可以查看如何从非托管应用程序调用托管代码以加载 .Net 库,并使用 gcroot 让非托管类维护对托管对象的引用它正在包装。
猜你喜欢
  • 2016-12-12
  • 2018-03-19
  • 2017-09-18
  • 2018-04-04
  • 2020-08-21
  • 2019-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多