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

发布于 2024-11-24 22:21:24 字数 1202 浏览 0 评论 0原文

在编写一些 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 ) );
    }
};

这符合要求,但函数转换不会在程序集之外公开可见,因为它在签名中使用非托管类型,请参见此处< a href="http://msdn.microsoft.com/en-us/library/ms235607%28v=VS.100%29.aspx" rel="nofollow">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 将是一个常见问题,但经过大量搜索后,我没有找到太多关于该主题的信息。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

日裸衫吸 2024-12-01 22:21:24

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

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.

栀子花开つ 2024-12-01 22:21:24

不是您问题的具体答案,但是,对于这些转换函数,我没有遇到像您这样的任何问题:

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

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());
        }
暮年 2024-12-01 22:21:24

在 DLL 之间传递 C++ 标准库类始终是个坏消息。如果可以的话,避免它。

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文