【问题标题】:Converting managed C++/CLI types to unmanaged types across assembly boundaries跨程序集边界将托管 C++/CLI 类型转换为非托管类型
【发布时间】:2011-10-07 14:19:50
【问题描述】:

一直在编写一些 C++/CLI 来包装现有的非托管 C++ 库,从托管类型转换为非托管类型的问题出现了。一个简单的例子是将 std::string 转换为 System::String 但该原理适用于许多类型,即数组 -> 向量。编写了一些转换函数后,我决定将它们打包到一个程序集中,以便我可以重用它们。鉴于全局 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 Unmanged STL 将是一个常见问题,但经过大量搜索后,我没有找到太多关于该主题的内容。

【问题讨论】:

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


【解决方案1】:

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

【讨论】:

  • +1;这些并不真的需要在一个程序集中。我更喜欢头文件中的内联函数——微软 C++ 支持库就是这样做的。
  • 我确实尝试了静态库方法,我必须承认我认为静态 .NET 程序集是不可能的。无论如何,链接器似乎确实生成了一个 .lib 文件。然后我尝试将其添加到链接器输入并得到未解析的符号。我还尝试在 .lib 上执行 #using,这给了我一个 C1113 #using failed 错误。我真的找不到任何关于如何在静态库中链接到 C++/CLI 代码的好文档。
【解决方案2】:

对于您的问题不是一个特定的答案,但是,对于这些转换功能,我没有像您这样的任何问题:

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

【讨论】:

  • 微软的 C++ 支持库(由 OP 的代码包装)已经处理了所有这些转换。
  • @Ben : 哦抱歉修复了那个。
  • 库确实已经提供了一些简单的转换。但是,我的问题适用于我想要执行的一系列更复杂的转换。我以字符串大小写为例。
【解决方案3】:

在 DLL 之间传递 C++ 标准库类总是坏消息。尽可能避免它。

【讨论】:

  • 这在很久以前可能是正确的,如果您使用混合标志,例如 dubug v 针对不同的 DLL 进行了优化,但与我在这篇文章中的问题并不真正相关,仍然如此,无论如何,谢谢。
猜你喜欢
  • 1970-01-01
  • 2019-07-14
  • 1970-01-01
  • 2012-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-14
  • 2011-07-12
相关资源
最近更新 更多