Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to export function with return type std::map in c++

I have a DLL project and a CLR project in visual c++.

The DLL project is the one that exporting std::map type function. And I will call that function from my CLR project.

From DLL project, 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));
    }
}

But when I tried to compile my DLL project, I got some errors:

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  

I can't find any solution related to this problem.

like image 381
noyruto88 Avatar asked Mar 07 '23 07:03

noyruto88


1 Answers

You cannot export non-trivial C++ classes with C linkage, and the compiler is telling you so in the error message.

The question is why do you use C linkage in the first place? If you don't have to use C linkage, don't use it. This will make things just more complicated as you need wrappers for almost everything. As long as you use the same compiler you'll be fine.

So in your header and source files, remove the extern "C" from the signature if you can (in either case: remove it from the source file, or else you redefine the function there which causes the latter 2 errors).

If you cannot remove the extern "C" part, try returning a void pointer (void*) instead of std::map and cast it to a map pointer in your CLR project. But this will force you to use managed C++ as CLR language.

I don't know what your CLR project is, but if it's written in managed C++ you can use all standard C++ types there aswell so C++ linkage is perfectly fine. If your CLR project is in a different language, like C#, consider making another project in managed C++ and use that as a wrapper like C# dll <--> managed C++ dll <--> C++ dll.

like image 88
Timo Avatar answered Mar 15 '23 09:03

Timo