【问题标题】:Exporting C++/CLI native class (C4679)导出 C++/CLI 本机类 (C4679)
【发布时间】:2013-06-19 14:07:12
【问题描述】:

我在 C++/CLI 程序集 (MyAssembly) 中有一个公共 ref 类,其中包含一个接受本机参数的公共静态方法。

#pragma make_public(nativeTypeA)

namespace namespaceA
{ 
    public ref class MyClass : namespaceB::MyClass
    {
    public:
        static managedTypeA ^ MethodA(nativeTypeA param);
        static managedTypeB ^ MethodB(nativeTypeB param);
    }
}

我想将此方法公开给另一个 C++/CLI 程序集。托管程序集可以正常编译,但引用它的程序集 (CallingAssembly) 会为 MethodB 生成以下警告:

warning C4679: 'namespaceA::MyClass::MethodB' : could not import member
This diagnostic occurred while importing type 'namespaceA::MyClass ' from assembly 'MyAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. 

我不能在 nativeTypeB 上使用 make_public,因为它是模板类的 typedef,但是,我将 make_public 用于非模板化的本机类型(例如 nativeTypeA)并且它可以工作(即编译 CallingAssembly 时没有 C4679)。正如this 帖子中所建议的那样,我没有使用make_public,而是将本机类声明为public,并通过预处理器指令在本机标头中使用了__declspec(dllexport)。还需要有条件地排除“public”修饰符(通过 CLR_ACCESS_MODIFIER),因为该类也包含在其他本地项目中:

#ifdef MANAGED
#define CLR_ACCESS_MODIFIER public 
#ifdef MYASSEMBLY_DEF
    #define MYASSEMBLY_LINKAGE __declspec(dllexport)
#else
    #define MYASSEMBLY_LINKAGE __declspec(dllimport)
#endif
#else
#define MYASSEMBLY_LINKAGE
#define CLR_ACCESS_MODIFIER
#endif

template<>
CLR_ACCESS_MODIFIER class MYASSEMBLY_LINKAGE nativeTypeB<TT> : public nativeTypeB_base<TT> {
...
}

我也为 nativeTypeB 的基类(编译所必需)和它的 typedef 做了这个:

typedef public nativeTypeB<TT> MYASSEMBLY_LINKAGE nativeTypeB;

我不确定上面的行是否必要,但 C4679 仍然会出现。

我已经完成了常规检查:在两个项目中都定义了 MANAGED 预处理器指令; MYASSEMBLY_DEF 在 MyAssembly 中定义;我在 CallingAssembly 中添加了对 MyAssembly 的引用,并将 MyAssembly.lib 添加到其链接行。项目构建顺序正确,没有缺少依赖项,但我仍然得到 C4679。

我可以更改接口以接受非模板类型,但我真的不想这样做,因为它会导致代码膨胀并且不那么优雅。 This 帖子提到在我的原生类中正常使用“public”应该可以工作。

谁能帮忙?

提前致谢!

【问题讨论】:

  • 那是行不通的,模板没有外部链接。使用普通的旧#include。
  • 您能否详细说明如何使用#include 来完成此任务?如果我只是在调用者的标题中#include MyClass.h,我会得到完全相同的 C4679 警告以及一系列其他错误,例如类类型重新定义,因为两个程序集中都有同名类。我尝试将 MethodB 设为私有并从 MyAssembly 中的公共代理方法调用它,但这并没有删除警告,考虑到调用者不应该看到私有方法,这似乎令人惊讶。
  • 同意。我喜欢上面链接帖子中的解决方案 2。
  • 我可能会通过一些重构来实现 Hans 的建议。这里讨论了相同的主题:stackoverflow.com/questions/12800262/…

标签: c++-cli


【解决方案1】:

跨 DLL 边界传递本机类的对象从来都不是一个好主意,因为它非常非常容易违反单一定义规则。

C++/CLI 对此没有任何帮助,相反,它提供了生成托管类型的能力,这些托管类型专为跨程序集共享而设计。它还可以防止您通过共享本机类型来招致灾难(违反 ODR)。您可以使用 make_public 杂注来覆盖它,但有限制(例如没有模板)。

共享本机类型的更好方法是通过 COM 样式的接口。

【讨论】:

  • 谢谢 - 很明显,我正在尝试的内容不受支持。我将修改接口以接受非模板类型。
猜你喜欢
  • 2011-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-16
  • 2011-05-20
  • 1970-01-01
相关资源
最近更新 更多