У меня возникла следующая проблема при использовании устаревшего VC6. Я просто не могу переключиться на современный компилятор, так как работаю над устаревшей базой кода.
http://support.microsoft.com/kb/172396
Так как нет способа экспортировать карту, мой запланированный обходной путь - использовать статическое связывание вместо динамического связывания.
Мне было интересно, сталкивались ли вы все с подобной ситуацией? Какой у вас обходной путь для этого?
Другим обходным решением является создание класса-оболочки вокруг карты stl, чтобы обеспечить создание и доступ к карте stl в пределах одного пространства DLL. Обратите внимание, что fun0, который использует класс-обертку, будет работать нормально. fun1 вылетит.
Вот пример кода:
// main.cpp. Compiled it as exe.
#pragma warning (disable : 4786)
#include <map>
#include <string>
template <class K, class V>
class __declspec(dllimport) map_wrapper {
public:
map_wrapper();
~map_wrapper();
map_wrapper(const map_wrapper&);
map_wrapper& operator=(const map_wrapper&);
V& operator[](const K&);
const V& operator[](const K&) const;
const V& get(const K&) const;
void put(const K&, const V&);
int size() const;
private:
std::map<K, V> *m;
};
__declspec(dllimport) void fun0(map_wrapper<std::string, int>& m);
__declspec(dllimport) void fun1(std::map<std::string, int>& m);
int main () {
map_wrapper<std::string, int> m0;
std::map<std::string, int> m1;
m0["hello"] = 888;
m1["hello"] = 888;
// Safe. The we create std::map and access map both in dll space.
fun0(m0);
// Crash! The we create std::map in exe space, and access map in dll space.
fun1(m1);
return 0;
}
// dll.cpp. Compiled it as dynamic dll.
#pragma warning (disable : 4786)
#include <map>
#include <string>
#include <iostream>
/* In map_wrapper.h */
template <class K, class V>
class __declspec(dllexport) map_wrapper {
public:
map_wrapper();
~map_wrapper();
map_wrapper(const map_wrapper&);
map_wrapper& operator=(const map_wrapper&);
V& operator[](const K&);
const V& operator[](const K&) const;
const V& get(const K&) const;
void put(const K&, const V&);
int size() const;
private:
std::map<K, V> *m;
};
/* End */
/* In map_wrapper.cpp */
template <class K, class V>
map_wrapper<K, V>::map_wrapper() : m(new std::map<K, V>()) {
}
template <class K, class V>
map_wrapper<K, V>::~map_wrapper() {
delete m;
}
template <class K, class V>
map_wrapper<K, V>::map_wrapper(const map_wrapper<K, V>& map) : m(new std::map<K, V>(*(map.m))) {
}
template <class K, class V>
map_wrapper<K, V>& map_wrapper<K, V>::operator=(const map_wrapper<K, V>& map) {
std::map<K, V>* tmp = this->m;
this->m = new std::map<K, V>(*(map.m));
delete tmp;
return *this;
}
template <class K, class V>
V& map_wrapper<K, V>::operator[](const K& key) {
return (*this->m)[key];
}
template <class K, class V>
const V& map_wrapper<K, V>::operator[](const K& key) const {
return (*this->m)[key];
}
template <class K, class V>
const V& map_wrapper<K, V>::get(const K& key) const {
return (*this->m)[key];
}
template <class K, class V>
void map_wrapper<K, V>::put(const K& key, const V& value) {
(*this->m)[key] = value;
}
template <class K, class V>
int map_wrapper<K, V>::size() const {
return this->m->size();
}
// See : http://www.parashift.com/c++-faq-lite/templates.html#faq-35.15
// [35.15] How can I avoid linker errors with my template classes?
template class __declspec(dllexport) map_wrapper<std::string, int>;
/* End */
__declspec(dllexport) void fun0(map_wrapper<std::string, int>& m) {
std::cout << m["hello"] << std::endl;
}
__declspec(dllexport) void fun1(std::map<std::string, int>& m) {
std::cout << m["hello"] << std::endl;
}