编译器错误C2158的最佳解决方法:make_public不支持本机模板类型 [英] Best workaround for compiler error C2158: make_public does not support native template types

查看:796
本文介绍了编译器错误C2158的最佳解决方法:make_public不支持本机模板类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个c ++ / cli dll(即编译/ clr)其中A.dll引用B.dll。在程序集B中,我有一个方法GetMgdClassB,我想从程序集A调用。这是程序集B(B.cpp)中的代码:

I have two c++/cli dlls (i.e. compiled with /clr) where A.dll references B.dll. In assembly B, I have a method, GetMgdClassB, I'd like to call from assembly A. Here is the code in assembly B (B.cpp):

namespace B
{
    public class NativeClassB
    {
    public:
        NativeClassB();
        // ... 
    };

    public ref class MgdClassB
    {
    public:
        static MgdClassB ^ GetMgdClassB(const std::vector<NativeClassB *> & vecNativeBs)
        {
            // ...
            vecNativeBs;
            return gcnew MgdClassB();
        }
    };
}



注意,GetMgdClassB方法需要一个std :: vector。在程序集A中,我尝试使用以下代码(A.cpp)调用此方法:

Notice that the method GetMgdClassB takes a std::vector. In assembly A, I attempt to call this method with the following code (A.cpp):

namespace B
{
    class NativeClassB;
}

#pragma make_public(std::vector<B::NativeClassB *>)

namespace A
{
    void Foo()
    {
        std::vector<B::NativeClassB *> vecNativeBs;
        B::MgdClassB::GetMgdClassB(vecNativeBs);
    }
}

当我编译A.cpp时,错误:

When I compile A.cpp, I get the following error:

error C2158: 'std::vector<_Ty>' : #pragma make_public directive is currently supported for native non-template types only

我想添加这个编译指示的原因是因为本机类型对程序集是私有的默认。如果我删除pragma我得到以下错误(如预期):

the reason I wanted to add this pragma is because native types are private to the assembly by default. If I remove the pragma I get the following error (as expected):

error C3767: 'B::MgdClassB::GetMgdClassB': candidate function(s) not accessible

因为模板实例化类型 std :: vector< B :: NativeClassB *> 对程序集是私有的。

since the template instantiation type std::vector<B::NativeClassB *> is private to the assembly.

更改方法 GetMgdClassB void * ,并将 std :: vector< NativeClassB *> 的地址传递给方法。在 GetMgdClassB 中。然后我可以 static_cast 传递 void * std :: vector< NativeClassB * ; * 。这当然是有效的,但打破了类型安全。

Change the method, GetMgdClassB to take a void * and pass the address of the std::vector<NativeClassB *> to the method. In GetMgdClassB. I can then static_cast the passed in void * to std::vector<NativeClassB *> *. This, of course, works, but breaks type safety.

创建托管类,例如 ref class NativeClassBWrapper 目的是挂起对本地NativeClassB的引用。更改GetMgdClassB以接受NativeClassBWrappers的受管容器(例如 List< NativeClassBWrapper ^> ^ )。这有一个缺点是必须在调用GetMgdClassB之前创建和填充一个新的托管容器,然后在托管类B中,我必须将它重新打包到原生容器 std :: vector< NativeClassB *> ;

Create a managed class, say ref class NativeClassBWrapper who's sole purpose is to hang on to a reference to the native NativeClassB. Change GetMgdClassB to take a managed container of NativeClassBWrappers (e.g. List<NativeClassBWrapper ^> ^). This has the downside of having to create and populate a new managed container prior to calling GetMgdClassB, and then within managed class B, I have to repackage it into the the native container std::vector<NativeClassB *> (since the code in B deals with this type.

目前,我倾向于使用解决方案#1,因为(a )它不会引入任何性能问题和(b)我只会在一些情况下这样做我不喜欢失去类型安全,但似乎是合理的给定的编译器的能力,使本地模板实例化类型可见。

Currently, I'm leaning toward going with Solution #1, since (a) it doesn't introduce any performance concerns and (b) I'll only be doing this in a few cases. I don't like losing the type safety, but it seems justifiable given the current deficiency in the compiler's ability to make native template instantiation types visible.

有更好的工作吗?

C ++ CLI候选函数无法访问

推荐答案

我不知道任何方式导出该类型。如果你必须有这个函数签名,我会倾向于使用托管和本地导出(使用本机类型的托管函数不能被其他语言使用)的方向,也许使用延迟加载当调用本机导出,所以你有机会陷阱错误查找程序集的通常的.NET方式。

I'm not aware of any way to export that type. If you have to have that function signature, I would lean in the direction of using a mix of managed and native exports (managed functions using native types can't be consumed by other languages anyway), and maybe use delay loading when calling the native exports so you have a chance to trap errors finding the assembly in the usual .NET way.

但是你的特定的函数可能有问题,因为它使用托管类型和复杂的本机

But your particular function may be problematic since it uses both managed types and complex native types in the signature.

一般来说,最好的做法是不要跨越DLL的边界传递本地C ++类,因为这将设置违反一个定义规则。

In general, the best practice is to not pass native C++ classes across DLL boundaries at all, since this sets you up for One Definition Rule violations.

对于这种特殊情况,我的建议是创建一个包装器实现 ICollection 。这解决了问题,就像你的解决方案#2,而不必实际将所有的元素复制到一个新的数据结构。

For this particular situation, my suggestion is to make an wrapper that implements ICollection. That cures the problem just like your solution #2, without ever having to actually copy all the elements into a new data structure.

这篇关于编译器错误C2158的最佳解决方法:make_public不支持本机模板类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆