我在visual c ++中有一个DLL项目和一个CLR项目。
DLL项目是导出std :: map类型函数的项目。我将从我的CLR项目中调用该函数。
来自DLL项目, staff.h
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://css-tricks.com/examples/HorzScrolling/jquery.mousewheel.js"></script>
<div class="horizontal-scroll">
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
staff.cpp
#ifdef STAFFS_EXPORTS
#define STAFFS_API __declspec(dllexport)
#else
#define STAFFS_API __declspec(dllimport)
#endif
#include <string>
#include <map>
namespace Staffs {
// other exported functions
....
//
extern "C" STAFFS_API auto GetStaffMap() -> std::map<int, std::string>;
}
但是当我尝试编译我的DLL项目时,我遇到了一些错误:
namespace Staffs {
std::map<int, std::string> staffMap;
extern "C" auto GetStaffMap() -> std::map<int, std::string> {
return staffMap;
}
void display_json(json::value const & jvalue, utility::string_t const & prefix)
{
// some code being skipped here
.......
//
staffMap.insert(std::make_pair(key, value));
}
}
我无法找到与此问题相关的任何解决方案。
答案 0 :(得分:6)
您无法使用C链接导出非平凡的C ++类,编译器会在错误消息中告诉您。
问题是为什么你首先使用C链接?如果您不必使用C链接,请不要使用它。这将使事情变得更加复杂,因为您需要几乎所有东西的包装器。只要您使用相同的编译器就可以了。
因此,在标题和源文件中,如果可以,请从签名中删除extern "C"
(在任何一种情况下:从源文件中删除它,否则您在那里重新定义函数这导致后两个错误)。
如果无法删除extern "C"
部分,请尝试返回空指针(void*
)而不是std::map
,并将其转换为CLR项目中的地图指针。但这会迫使您使用托管C ++作为CLR语言。
我不知道您的CLR项目是什么,但如果它是用托管C ++编写的,那么您可以使用所有标准C ++类型,因此C ++链接非常好。如果您的CLR项目使用不同的语言(如C#),请考虑在托管C ++中创建另一个项目,并将其用作C# dll <--> managed C++ dll <--> C++ dll
之类的包装器。
答案 1 :(得分:1)
我对这类问题没有经验,但是如何创建像:
这样的函数extern "C" STAFFS_API const char* GetStaffMapValue(int key);
和
extern "C" const char* GetStaffMapValue(int key) {
auto it = staffMap.find(key);
if (it == staffMap.end())
return nullptr;
else
return it->second.c_str();
}
您当然可以类似地为地图修饰符创建包装器,例如,用于插入新元素。