Converting managed C++/CLI types to unmanaged types across assembly boundaries
Having been writing some C++/CLI to wrap an existing unmanaged C++ library the issue of converting from managed types to unmanaged types came up. A simple example off this is converting a std::string to a System::String but the principle applies to many types i.e. array -> vector. Having written some conversion function I decided to package them up in an Assembly so I can re-use them. Given that global C++/CLI functions are not visible outside the current Assembly I ended up with things like this
public ref class ClassJustToContainStaticFunctions
{
public:
static std::string convert( System::String^ s )
{
msclr::intero开发者_StackOverflow中文版p::marshal_context context;
return( context.marshal_as<std::string>( s ) );
}
};
This complies fine but the function convert does not get made publicly visible outside the Assembly because it uses an unmanaged type in the signature, see here http://msdn.microsoft.com/en-us/library/ms235607%28v=VS.100%29.aspx for more on this. The solution is normally to add
#pragma make_public(std::string)
to the file and I have done this in other situations without problems. However make_public does not work for templated classes like std::string. See here http://msdn.microsoft.com/en-us/library/ms235343%28v=vs.80%29.aspx for some info.
I found a few attempts at work arounds for instance but they all seemed pretty ugly.
So, after all that, my question is am I missing something obvious here? It seems to me that converting from managed to unmanaged types, particularly for things like container classes i.e. STL.NET <--> Unmanged STL would be a common issue but after much searching I haven't found much on the topic.
As these functions are only needed in mixed mode programming, wrap them up in some header files / static library instead of an assembly. This way you can re-use them in every program but you are not dependent on them being exported.
Not a particular answer for your question but, I do not have any problems like yours, with those conversion functions :
static void StringToStdString ( String ^ s, std::string& os )
{
using namespace Runtime::InteropServices;
const char* chars = (const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();
os = chars;
Marshal::FreeHGlobal(IntPtr((void*)chars));
}
static const char * StringToCharPtr ( String ^ s)
{
using namespace Runtime::InteropServices;
const char* chars = (const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();
return chars;
}
static String^ StdStringToString(const std::string& _is)
{
return gcnew String(_is.c_str());
}
Passing C++ standard library classes between DLLs is always bad news. Avoid it if you possibly can.
精彩评论