将托管C ++ / CLI类型转换为跨程序集边界的非托管类型

时间:2011-07-18 11:02:44

标签: .net stl c++-cli interop mixed-mode

编写了一些C ++ / CLI来包装现有的非托管C ++库时,出现了从托管类型转换为非托管类型的问题。一个简单的例子是将std :: string转换为System :: String,但该原则适用于许多类型,即array - >向量。编写了一些转换函数后,我决定将它们打包成一个程序集,以便我可以重用它们。鉴于全局C ++ / CLI函数在当前程序集之外不可见,我最终得到了类似这样的东西

public ref class ClassJustToContainStaticFunctions
{
public:

    static std::string convert( System::String^ s )
    {           
        msclr::interop::marshal_context context;

        return( context.marshal_as<std::string>( s ) );
    }
};

这符合要求,但函数convert在大会之外不会公开显示,因为它在签名中使用了非托管类型,有关详细信息,请参阅此处http://msdn.microsoft.com/en-us/library/ms235607%28v=VS.100%29.aspx。解决方案通常是添加

#pragma make_public(std::string)

到文件,我在其他情况下完成了这个没有问题。但是make_public不适用于像std :: string这样的模板化类。有关详细信息,请参阅此处http://msdn.microsoft.com/en-us/library/ms235343%28v=vs.80%29.aspx

我发现有几次尝试工作,但它们看起来都很难看。

所以,毕竟,我的问题是我错过了一些明显的东西吗?在我看来,从托管类型转换为非托管类型,特别是对于像容器类这样的东西,即STL.NET&lt; - &gt;。无人值守的STL将是一个常见的问题,但经过大量的搜索后,我没有找到很多关于这个话题。

3 个答案:

答案 0 :(得分:2)

由于这些功能仅在混合模式编程中需要,所以将它们包装在一些头文件/静态库中而不是程序集中。这样您就可以在每个程序中重复使用它们,但不依赖于它们的导出。

答案 1 :(得分:0)

对于您的问题,这不是一个特别的答案,但是,我没有像你这样的问题,有这些转换函数:

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

答案 2 :(得分:-1)

在DLL之间传递C ++标准库类总是坏消息。如果可能,请避免使用它。