- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
[DllImport("foo.dll", CharSet = CharSet.Unicode)]
static extern void Process_utf16(string text, int text_length);
native 函数被编写为接收 utf-16 数据(这也是 .net 字符串使用的。)它返回后不使用字符串数据。因此,我试图确保直接传递指向字符串缓冲区的指针,而不进行任何不必要的分配或复制。
在这个声明中,是否传递了一个指向字符串缓冲区的指针而没有分配?还是分配了临时缓冲区并将字符串复制到其中?如果发生分配,是分配给 native 堆还是托管堆?谁负责解除分配?
请注意,上面的代码已经过测试并且可以工作,我只是想看看它是否会导致分配和复制,如果是,如何避免。
最佳答案
"Default Marshaling for Strings" 中描述了编码字符串的规则。 .对于 native 功能(平台互操作),文档指定:
Platform invoke copies string arguments, converting from the .NET Framework format (Unicode) to the platform unmanaged format. Strings are immutable and are not copied back from unmanaged memory to managed memory when the call returns.
但是,正如可以通过实验简单确定的那样,如果根本不需要转换,即该方法用 CharSet.Unicode
修饰,则这不正确或者该字符串被显式标记为 MarshalAs(UnmanagedType.LPWStr)
。在这种情况下,直接传递指向字符串内容的指针。这听起来非常有效,确实如此,但它也很危险,因为没有什么可以阻止非托管函数修改传递给它的字符串。这很糟糕,因为 .NET 字符串应该是不可变的,并且代码可能依赖于此。如果这最终会覆盖字符串实习生池,那就特别糟糕了。
trample.c
:
__declspec(dllexport) void __stdcall Trample(wchar_t* text) {
memcpy(text, L"Adios", (sizeof L"Adios") - 2);
}
程序.cs
:
static class NativeMethods {
[DllImport("trample.dll", CharSet = CharSet.Unicode)]
public static extern void Trample(string text);
}
class Program {
static void Main(string[] args) {
Console.WriteLine("Hello, world!");
NativeMethods.Trample("Hello, world!");
Console.WriteLine("Hello, world!");
}
}
输出:
Hello, world!
Adios, world!
因为 "Hello, world!"
是一个字符串文字,它的所有实例最终都在字符串实习池中,并且每次使用它时我们都使用“相同”的字符串。我们的非托管函数覆盖了它,所以现在每当我们认为我们在我们的托管代码中编写 "Hello, world!"
时,我们最终会得到其他东西。糟糕。
如果您知道非托管函数会更改字符串,避免这种情况的方法是改为传递 StringBuilder
。在这里您甚至可以选择是否要复制到输入、输出或两者(使用 InAttribute
/OutAttribute
)。这确实涉及复制到缓冲区/从缓冲区复制——具体来说,CoTaskMemAlloc
将用于为非托管代码分配内存(并且 CoTaskMemFree
将在调用完成时调用)。此代码作为调用的一部分由编码(marshal)拆收器调用;托管调用者和非托管调用者都不需要关心这个。
调用需要 ANSI 字符串的函数也涉及分配缓冲区,但在这种情况下,缓冲区是使用 localloc
指令分配的,而不是 CoTaskMemAlloc
,它是 bunches更高效。也就是说——如果您实际上是为了提高效率,那么您要做的是尽可能完全消除调用非托管代码,而不仅仅是优化字符串传递。即使忽略复制内存,托管/非托管转换也涉及相当多的开销。如果您发现自己在循环中调用非托管代码,那么查看该代码是否可以移植到托管代码是值得的。
来源:coreclr/src/vm/ilmarshalers.cpp
, 具体来说 ILWSTRMarshaler::EmitConvertSpaceAndContentsCLRToNativeTemp
.
关于c# - 在 DllImport 中指定 Charset.Unicode 是否分配字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43077734/
所以,据我所知,这个类并不存在于标准 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 的
我是一名优秀的程序员,十分优秀!