У меня есть два 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
причина, по которой я хотел добавить эту прагму, заключается в том, что по умолчанию собственные типы являются частными для сборки. Если я удаляю прагму, я получаю следующую ошибку (как и ожидалось):
error C3767: 'B::MgdClassB::GetMgdClassB': candidate function(s) not accessible
, поскольку тип экземпляра шаблона std::vector<B::NativeClassB *>
является закрытым для сборки.
Попытки решения
1. Используйте void *, безопасность типа прерывания:
Измените метод, GetMgdClassB
, чтобы взять void *
и передать адрес std::vector<NativeClassB *>
методу. В GetMgdClassB
. Затем я могу static_cast
передать в void *
до std::vector<NativeClassB *> *
. Это, конечно, работает, но нарушает безопасность типов.
2. Создайте управляемую оболочку для NativeClassB, передайте управляемый контейнер
Создайте управляемый класс, скажем ref class NativeClassBWrapper
, единственной целью которого является сохранение ссылки на нативный NativeClassB. Измените GetMgdClassB на управляемый контейнер NativeClassBWrappers (например, List<NativeClassBWrapper ^> ^
). Недостатком этого является необходимость создания и заполнения нового управляемого контейнера перед вызовом GetMgdClassB, а затем в управляемом классе B я должен упаковать его в собственный контейнер std::vector<NativeClassB *>
(поскольку код в B имеет дело с этим типом.
В настоящее время я склоняюсь к решению № 1, поскольку (а) оно не вызывает проблем с производительностью и (б) я буду делать это только в нескольких случаях. Мне не нравится терять безопасность типов, но это кажется оправданным, учитывая текущий недостаток способности компилятора делать видимыми типы создания экземпляров шаблонов.
Вопрос:
Есть ли лучшие способы обхода?
Связанный вопрос:
C ++ CLI error C3767: функции-кандидаты недоступны