- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这是我之前问题的后续问题:Does .NET interop copy array data back and forth, or does it pin the array?
我的方法是 COM 接口(interface)方法(而不是 DllImport
方法)。 C# 签名如下所示:
void Next(ref int pcch,
[In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)]
char [] pchText);
MSDN says :
When a managed Char type, which has Unicode formatting by default, is passed to unmanaged code, the interop marshaler converts the character set to ANSI. You can apply the DllImportAttribute attribute to platform invoke declarations and the StructLayoutAttribute attribute to a COM interop declaration to control which character set a marshaled Char type uses.
此外,@HansPassant 在他的回答中 here says :
A char[] can't be marshaled as LPWStr, it has to be LPArray. Now the CharSet attribute plays a role, since you did not specify it, the char[] will be marshaled as an 8-bit char[], not a 16-bit wchar_t[]. The marshaled array element is not the same size (it is not "blittable") so the marshaller must copy the array.
Pretty undesirable, particularly given that your C++ code expects wchar_t. A very easy way to tell in this specific case is not getting anything back in the array. If the array is marshaled by copying then you have to tell the marshaller explicitly that the array needs to be copied back after the call. You'd have to apply the [In, Out] attribute on the argument. You'll get Chinese.
我找不到 CharSet
的类似物(通常与 DllImportAttribute
和 StructLayoutAttribute
一起使用)可以应用于 COM 接口(interface)方法。
然而,我没有在输出中得到“中文”。一切似乎都运行良好,我确实从 COM 返回了正确的 Unicode 字符。
这是否意味着对于 COM 方法互操作,Char
总是被解释为 WCHAR
?
我找不到任何证实或否认这一点的文件。
最佳答案
我认为这是一个很好的问题,char
(System.Char
) 互操作行为确实值得关注。
在托管代码中,sizeof(char)
始终等于 2
(两个字节),因为在 .NET 中字符始终是 Unicode。
然而,当 char
用于 P/Invoke(调用导出的 DLL API)和 COM(调用 COM 接口(interface)方法)时,编码规则不同。
对于 P/Invoke,CharSet
可以显式地与任何 [DllImport]
属性一起使用,或通过 [module|assembly: DefaultCharSet(CharSet.Auto|Ansi|Unicode)]
隐式地使用,以更改默认设置对于每个模块或每个程序集的所有 [DllImport]
声明。
默认值是CharSet.Ansi
,这意味着会有Unicode到ANSI的转换。我通常使用 [module: DefaultCharSet(CharSet.Unicode)]
将默认值更改为 Unicode,然后在那些罕见的情况下选择性地使用 [DllImport(CharSet = CharSet.Ansi)]
我需要调用 ANSI API 的情况。
还可以使用 MarshalAs(UnmanagedType.U1|U2)
或 MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1|U2)
(对于 char[]
参数)。例如,您可能有这样的事情:
[DllImport("Test.dll", ExactSpelling = true, CharSet = CharSet.Unicode)]
static extern bool TestApi(
int length,
[In, Out, MarshalAs(UnmanagedType.LPArray] char[] buff1,
[In, Out, MarshalAs(UnmanagedType.LPArray,
ArraySubType = UnmanagedType.U1)] char[] buff2);
在这种情况下,buff1
将作为双字节值数组传递(按原样),但 buff2
将与单字节数组相互转换字节值。请注意,对于 buff2
,这仍然是一种智能的 Unicode 到 OS 当前代码页(和返回)转换。例如,Unicode '\x20AC' (€
) 在非托管代码中将变为 \x80
(假设操作系统代码页为 Windows-1252
).这就是 MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1)] char[] buff
与 MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1)] ushort 的不同之处[] 浅黄色
。对于 ushort
,0x20AC
将简单地转换为 0xAC
。
对于调用 COM 接口(interface)方法,情况就完全不同了。在那里,char
始终被视为表示 Unicode 字符的双字节值。也许,这种设计决策的原因可以从 Don Box 的“Essential COM”中得到暗示(引用来自 this page 的脚注):
The
OLECHAR
type was chosen in favor of the commonTCHAR
data type used by the Win32 API to alleviate the need to support two versions of each interface (CHAR
andWCHAR
). By supporting only one character type, object developers are decoupled from the state of the UNICODE preprocessor symbol used by their clients.
显然,同样的概念也进入了 .NET。我非常有信心即使对于遗留的 ANSI 平台也是如此(例如 Windows 95,其中 Marshal.SystemDefaultCharSize == 1
)。
请注意,当 DefaultCharSet
是 COM 接口(interface)方法签名的一部分时,它对 char
没有任何影响。也没有办法显式应用 CharSet
。但是,您仍然可以使用 MarshalAs
完全控制每个单独参数的编码行为,其方式与上面的 P/Invoke 完全相同。例如,您的 Next
方法可能如下所示,以防非托管 COM 代码需要一个 ANSI 字符缓冲区:
void Next(ref int pcch,
[In, Out, MarshalAs(UnmanagedType.LPArray,
ArraySubType = UnmanagedType.U1, SizeParamIndex = 0)] char [] pchText);
关于c# - COM 方法、Char 类型和 CharSet,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25039290/
所以,据我所知,这个类并不存在于标准 Java 库中,而是 Dalvik 中的新增内容。这是正确的吗? 我认为这是 android 类“NdefRecord”包含对它的引用并使用它的原因,但无法将其导
我想创建一些处理编码的示例程序,特别是我想使用宽字符串,例如: wstring a=L"grüßen"; wstring b=L"שלום עולם!"; wstring c=L"中文"; 因为这些是
有人知道一种更快的方法来完成 java.nio.charset.Charset.decode(..)/encode(..) 的功能吗? 这是我目前使用的技术的瓶颈之一。 [编辑]具体来说,在我的应用程
我想创建一些处理编码的示例程序,特别是我想使用宽字符串,例如: wstring a=L"grüßen"; wstring b=L"שלום עולם!"; wstring c=L"中文"; 因为这些是
我正在检查代码并遇到以下行。 Charset.forName("ASCII") 但是当我查看 java documentation它只有 US-ASCII ISO-8859-1 UTF-8
初始化 PDO 时 - 我应该做:charset=UTF8 还是 charset=UTF8MB4? 这是我的初始化: $dsn = 'mysql:host=example.com;dbname=tes
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 9 年前。 Improve
据我所知,在 String.getBytes(charset) 中,参数 charset 表示该方法返回编码为给定字符集的字符串字节。 在 new String(bytes, charset) 中,第
我正在使用 sqlsrv 驱动程序连接到带有 PDO 的 MS SQL 服务器。 PHP 版本为 5.3.24。工作连接如下所示: $dsny = "sqlsrv:Server=xx1;Databas
我的算法有两个输入: 1 个将被编码的 utf8 String 对象 1 个字符集对象,指示我需要将字符串编码成什么 最后,返回的结果将被放入一个OutputStream,一个可能发生多次但至少一次的
获取多个字符集:text/json; Charset=UTF-8;charset=utf-8 OkHttp Header 调用 okHttp Library 服务器时。有人知道我该如何解决这个问题。
使用 firebug 时,我在我的 asp.net mvc 4 项目中收到此连线错误“NetworkError: 415 Cannot process the ...xt/xml; charset=u
当我尝试通过 ant 运行我的 TestNG 测试时,我得到了 java.lang.NoSuchMethodError: org.springframework.http.MediaType.getC
我正在使用 .NET 4.0 在 IIS 7.5 中托管 WCF 服务。我还有一个 WPF 应用程序,用作我的客户端,它是使用 Visual Studio 2010 和 .NET 4.0 构建的。我添
我一直在尝试向 soap 服务器发送正确的请求。我不断收到错误消息。 这是我的xml GET LAST REQUEST(添加换行符): 1 获取最后的回复: 请求 header : POST /
我在通过 ajax json 调用 WCF 服务时收到上述响应。我的调用代码是: $(document).ready(function () { $.ajax
我尝试使用独立应用程序使用 WCF Web 服务。我可以使用 Internet Explorer 查看此服务,也可以在 Visual Studio 服务引用中查看。 这是我遇到的错误 The cont
我使用独立应用程序创建了 WCF 服务并测试了 WCF 客户端。我能够使用 Internet Explorer 查看此服务,也能够在 Visual Studio 服务引用中查看。这是错误消息。 “响应
我们有一个在 HTTPS 上运行良好但在 HTTPS 上显示 HTTP 415 错误的网络服务。因此,在 HTTP 下,我们可以毫无问题地发送和接收 JSON 的 POST 请求。当我们在 HTTPS
我正在将 spring-boot 从 1.3.6 更新到 2.1.3,而之前响应的内容类型为 application/json;charset=UTF-8 ,现在我得到了一个 iso-8859-1 的
我是一名优秀的程序员,十分优秀!