You can't do it directly - you need an extra level of indirection. For a C-style compatible interface you'll need to return a primitive type. Forget about using C++ DLLs from any other compiler - there is no strict C++ ABI.
So, you'd need to return a opaque pointer to an allocated string vector, e.g.
#define MYAPI __declspec(dllexport) extern "C" { struct StringList; MYAPI StringList* CreateStringList(); MYAPI void DestroyStringList(StringList* sl); MYAPI void GetDeviceList(StringList* sl); MYAPI size_t StringList_Size(StringList* sl); MYAPI char const* StringList_Get(StringList* v, size_t index); }
And implementation wise:
std::vector<std::string>* CastStringList(StringList* sl) { return reinterpret_cast<std::vector<std::string> *>(sl); } StringList* CreateStringList() { return reinterpret_cast<StringList*>(new std::vector<std::string>); } void DestroyStringList(StringList* sl) { delete CastStringList(sl); } void GetDeviceList(StringList* sl) { *CastStringList(sl) = GetStrings(); // or whatever } size_t StringList_Size(StringList* sl) { return CastStringList(sl)->size(); } char const* StringList_Get(StringList* v, size_t index) { return (*CastStringList(sl))[index].c_str(); }
After doing all of this you can then provide a cleaner wrapper on the C# end. Don't forget to destroy the allocated object via the DestroyStringList function, of course.