Как экспортировать функцию с возвращаемым типом std :: map в c ++ - PullRequest
0 голосов
/ 03 мая 2018

У меня есть проект DLL и проект CLR в Visual C ++.

Проект DLL - это тот, который экспортирует функцию типа std :: map. И я назову эту функцию из моего проекта CLR.

Из проекта DLL, staff.h

#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>;
} 

staff.cpp

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));
    }
}

Но когда я попытался скомпилировать свой проект DLL, я получил несколько ошибок:

Error   C2526   'GetStaffMap': C linkage function cannot return C++ class 'std::map<int,std::string,std::less<int>,std::allocator<std::pair<const _Kty,_Ty>>>'  AmsCppRest  c:\users\laptop-attendance\source\repos\amscpprest\amscpprest\staff.h   18  

Error   C2556   'std::map<int,std::string,std::less<int>,std::allocator<std::pair<const _Kty,_Ty>>> Staffs::GetStaffMap(void)': overloaded function differs only by return type from 'void Staffs::GetStaffMap(void)'   AmsCppRest  c:\users\laptop-attendance\source\repos\amscpprest\amscpprest\staff.cpp 38  

Error   C2371   'Staffs::GetStaffMap': redefinition; different basic types  AmsCppRest  c:\users\laptop-attendance\source\repos\amscpprest\amscpprest\staff.cpp 38  

Я не могу найти решение, связанное с этой проблемой.

Ответы [ 2 ]

0 голосов
/ 03 мая 2018

Вы не можете экспортировать нетривиальные классы C ++ со связью C, и компилятор сообщает вам об этом в сообщении об ошибке.

Вопрос в том, почему вы в первую очередь используете связь С? Если вам не нужно использовать связь C, не используйте ее. Это усложнит ситуацию, поскольку вам нужны обертки практически для всего. Пока вы используете один и тот же компилятор, все будет в порядке.

Итак, в ваших заголовочных файлах и удалите extern "C" из подписи, если можете (в любом случае: удалите его из исходного файла, или вы переопределите там функцию, которая вызывает последние 2 ошибки).

Если вы не можете удалить часть extern "C", попробуйте вернуть указатель void (void*) вместо std::map и приведите его к указателю карты в вашем проекте CLR. Но это заставит вас использовать управляемый C ++ в качестве языка CLR.

Я не знаю, каков ваш CLR-проект, но если он написан на управляемом C ++, вы также можете использовать все стандартные типы C ++, так что связь с C ++ вполне подойдет. Если ваш CLR-проект написан на другом языке, например C #, рассмотрите возможность создания другого проекта в управляемом C ++ и используйте его в качестве оболочки, например C# dll <--> managed C++ dll <--> C++ dll.

0 голосов
/ 03 мая 2018

У меня нет опыта решения подобных проблем, но как насчет создания такой функции, как:

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();          
}

Конечно, вы можете аналогичным образом создавать оболочки для модификаторов карты, например, для вставки новых элементов.

...