2

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::interop::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.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
goneskiing
  • 1,659
  • 1
  • 13
  • 22
  • Related question: http://stackoverflow.com/questions/4121249/best-workaround-for-compiler-error-c2158-make-public-does-not-support-native-tem for reference – Matt Smith Jul 18 '11 at 20:18
  • I had already read the 4121249 question, it was one of the "pretty ugly" work arounds I mentioned. Thanks anyway – goneskiing Jul 23 '11 at 13:26

3 Answers3

2

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.

JoeG
  • 12,994
  • 1
  • 38
  • 63
Tobias Langner
  • 10,634
  • 6
  • 46
  • 76
  • +1; These don't really need to be in an assembly. I'd favour inline functions in a header - that's how the Microsoft C++ support library does it. – JoeG Jul 18 '11 at 13:18
  • I did try the static library approach, I must admit I didn't think static .NET assemblies were possible. Anyway the linker did seem to produce a .lib file. I then tried adding that to the linker inputs and got unresolved symbols. I also tried doing a #using on the .lib which gave me a C1113 #using failed error. I can't really find any good documents on how to link to C++/CLI code in a static library. – goneskiing Jul 23 '11 at 13:30
0

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());
        }
ali_bahoo
  • 4,732
  • 6
  • 41
  • 63
  • Microsoft's C++ support library, which the OP's code is wrapping, already handles all those conversions. – JoeG Jul 18 '11 at 13:16
  • @Ben : Oh sorry fixed that one. – ali_bahoo Jul 19 '11 at 07:18
  • It is true that the library already provides some simple conversions. However my issue applies to a whole range of more complex conversions I would like to perform. I was using the string case as an example. – goneskiing Jul 23 '11 at 13:36
-1

Passing C++ standard library classes between DLLs is always bad news. Avoid it if you possibly can.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • This may have been true a long time ago, and still is if you use a mixture of flags, dubug v's optimized for instance, for different DLL's but is not really relevant to my issue in this post, Thanks anyway. – goneskiing Jul 23 '11 at 13:34