如何正确地将.NET字符串编组为本地代码的std :: wstrings? [英] How to correctly marshal .NET Strings to std::wstrings for native code?

查看:87
本文介绍了如何正确地将.NET字符串编组为本地代码的std :: wstrings?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个第三方库,该库具有一个类,其中构造函数使用std::wstring.

I have a third party library which has a class where the constructor takes a std::wstring.

构造函数由第三方在头文件中定义,如下所示:

The constructor is defined by the third party like this in the header file:

Something(const std::wstring &theString);

我的头文件有这个:

extern "C" __declspec(dllexport) ThirdParty::Something* createSomething(const std::wstring &theString);

我的实现是这样的:

ThirdParty::Something* Bridge::createSomething(const std::wstring &theString) {
    return new ThirdParty::Something(theString);
}

现在在我的C#示例程序中,我有:

Now in my C# example program I have:

[DllImport("Bridge.dll", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Unicode)]
public static extern IntPtr createSomething(StringBuilder theString);

当我现在这样称呼时:

IntPtr ip = createSomething(new StringBuilder("foo"));

我得到一个AccessViolationException.当我使用String而不是StringBuilder时,会得到一个SEHException.

I get an AccessViolationException. When I use String instead of StringBuilder I get a SEHException.

我缺少什么或做错了什么?

What am I missing or doing incorrectly?

编辑,当我只是在createSomething函数中使用return 0时,在使用String时会得到一个StackImbalanceException.

EDIT when I just return 0 in the createSomething function I get a StackImbalanceException when using String.

推荐答案

我不认为现成的.Net编组器支持C ++ ABI.

I don't believe the C++ ABI is supported in the .Net marshaller out the box.

您需要将.Net字符串编组为wchar_t*,然后在本机端创建std::wstring.

You would need to marshal the .Net String to a wchar_t* and then create the std::wstring on the native side.

或者,您可以使用C ++/CLI(假设msvc)为您提供两者的中介(通过 marshal_as ),它了解.Net字符串,并具有编组器将其编组为std::wstring.微软提供了几种标准的元帅,请参见其此处概述.

Alternatively you could use the C++/CLI (assuming msvc) to mediate the two for you (via marshal_as), it understands the .Net String and has marshaller to marshal it the std::wstring. Microsoft provides several standard marshalers, see their overview here.

我的经验通常是,在这种情况下C ++/CLI存根更加整齐和容易(您的里程会在此处有所不同),否则,您可以尝试为第三方库提供纯的C样式API,以用于你.

My experience has generally been that the C++/CLI stub is neater and easier in these situations (your mileage will vary here), else you could try to get the third party library to be provided with a plain C-style API for you.

您的示例代码将提示您可能已经在您的控制范围内的Bridge代码段.考虑使网桥中的接口尽可能简单(内置类型,POD等),并且应该简化第三方库的集成.

Your sample code hints at a Bridge piece of code that may already be under your control. Consider keeping the interface in the bridge as simple as possible (built in types, PODs etc.) and it should simplify the integration of the third party library.

还值得注意的是,如果您要链接到第三方的C ++库,请使用相同的编译器,设置,调用约定和运行时等.这样做,否则您仍然会遇到ABI问题.为外部库提供导出的C ++接口(包括STL)并不是一个好主意.

It is also worth noting that, if you are going to link against the C++ library of the third party, is to use the same compiler, settings, calling conventions and the runtime etc. as they do, else you will still run into ABI issues. It isn't always a good idea to provide external libraries with export C++ interfaces (including the STL).

基本上,有几种方法可以将这些代码链链接在一起,您将不得不选择一种适合所用工具链的方法.

Basically there are a few ways to chain these pieces of code together, you will have to pick one that suits the tools chains being used.

这篇关于如何正确地将.NET字符串编组为本地代码的std :: wstrings?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆