我有两个 c++/cli dll(即用 /clr 编译),其中 A.dll 引用 B.dll。在程序集 B 中,我有一个方法 GetMgdClassB,我想从程序集 A 调用。这是程序集 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) 调用此方法:
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 时,我收到以下错误:
error C2158: 'std::vector<_Ty>' : #pragma make_public directive is currently supported for native non-template types only
我想添加这个 pragma 的原因是因为默认情况下本机类型是程序集私有的。如果我删除编译指示,我会收到以下错误(如预期的那样):
error C3767: 'B::MgdClassB::GetMgdClassB': candidate function(s) not accessible
因为模板实例化类型std::vector<B::NativeClassB *>
是程序集私有的。
尝试的解决方案
1.使用void *,break类型安全:
更改方法,GetMgdClassB
获取 avoid *
并将其地址传递std::vector<NativeClassB *>
给方法。在GetMgdClassB
. 然后我可以static_cast
传入void *
到std::vector<NativeClassB *> *
. 当然,这可行,但会破坏类型安全。
2.为NativeClassB创建一个Managed wrapper,传递一个托管容器
创建一个托管类,说ref class NativeClassBWrapper
谁的唯一目的是保留对本机 NativeClassB 的引用。更改 GetMgdClassB 以获取 NativeClassBWrappers 的托管容器(例如List<NativeClassBWrapper ^> ^
)。这样做的缺点是必须在调用 GetMgdClassB 之前创建和填充一个新的托管容器,然后在托管类 B 中,我必须将它重新打包到本机容器中std::vector<NativeClassB *>
(因为 B 中的代码处理这种类型。
目前,我倾向于使用解决方案 #1,因为 (a) 它不会引入任何性能问题,并且 (b) 我只会在少数情况下这样做。我不喜欢失去类型安全,但考虑到当前编译器使本机模板实例化类型可见的能力不足,这似乎是合理的。
问题:
有更好的解决方法吗?