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



在编写一些c++/CLI来包装现有的非托管c++库时,出现了从托管类型转换为非托管类型的问题。一个简单的例子是将std::string转换为System:: string,但该原则适用于许多类型,例如array -> vector。在编写了一些转换函数之后,我决定将它们打包到一个程序集中,以便我可以重用它们。考虑到全局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 <->未管理的STL将是一个常见的问题,但经过多次搜索,我没有发现太多关于该主题的内容。

由于这些函数只在混合模式编程中需要,所以将它们包装在一些头文件/静态库中,而不是汇编中。这样,你可以在每个程序中重用它们,但你不依赖于它们被导出。

对于您的问题没有特定的答案,但是,我没有像您这样的问题,使用这些转换函数:

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

在dll之间传递c++标准库类总是坏消息。

最新更新