- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我已经更新到 swift 5,我使用的依赖项之一无法在 swift 5 中编译。我已经修复了它,但现在我在整个文件中收到了 350 多个弃用警告。它们都与此类似:
withUnsafeMutableBytes
is deprecated: usewithUnsafeMutableBytes<R>(_: (UnsafeMutableRawBufferPointer) throws -> R) rethrows -> R
instead
这是代码片段(它基本上只是调用 c 库的函数):
var k = Data(count: crypto_generichash_keybytes())
k.withUnsafeMutableBytes { kPtr in
flutter_sodium.crypto_generichash_keygen(kPtr)
}
作为引用,在上面的 crypto_generichash_keybytes() 中只返回一个 size_t 和 crypto_generichash_keygen
的签名是void crypto_generichash_keygen(unsigned char k[crypto_generichash_KEYBYTES]);
.
我发现(如 this answer 所述)解决这个问题的方法应该是调用 kPtr.baseAddress:
var k = Data(count: crypto_generichash_keybytes())
k.withUnsafeMutableBytes { kPtr in
flutter_sodium.crypto_generichash_keygen(kPtr.baseAddress)
}
因为那应该使用 withUnsafeMutableBytes<ResultType>
变体而不是已弃用的 withUnsafeMutableBytes<ResultType, ContentType>
.但是,这反而会导致错误
value of type 'UnsafeMutablePointer<_>' has no member 'baseAddress'.
如果我明确指定 resultType 和 kPtr:
var k = Data(count: crypto_generichash_keybytes())
k.withUnsafeMutableBytes { (kPtr: UnsafeMutableRawBufferPointer) -> Void in
flutter_sodium.crypto_generichash_keygen(kPtr.baseAddress)
}
我反而得到
UnsafeMutableRawBufferPointer' is not convertible to 'UnsafeMutablePointer<_>'.
是否有任何快速的专家可以帮助我找出正确的方法来做到这一点?我知道警告只是警告,但我更喜欢编译时没有警告的代码。
我看了一下Swift 5.0: 'withUnsafeBytes' is deprecated: use `withUnsafeBytes<R>(...)在发布这个问题之前,它对我的情况没有帮助,因为我没有加载指针而是使用数据。此外,我已经完全按照文档中的指示进行操作,但这仍然无济于事。
编辑:为了更清楚一点,350 多个警告中的一些与 Data
的代码相关。在代码中分配,但是其中一些是我收到 Data
的地方来自外部来源。看起来像这样:
let args = call.arguments as! NSDictionary
let server_pk = (args["server_pk"] as! FlutterStandardTypedData).data
let server_sk = (args["server_sk"] as! FlutterStandardTypedData).data
let client_pk = (args["client_pk"] as! FlutterStandardTypedData).data
var rx = Data(count: flutter_sodium.crypto_kx_sessionkeybytes())
var tx = Data(count: flutter_sodium.crypto_kx_sessionkeybytes())
let ret = rx.withUnsafeMutableBytes { rxPtr in
tx.withUnsafeMutableBytes { txPtr in
server_pk.withUnsafeBytes { server_pkPtr in
server_sk.withUnsafeBytes { server_skPtr in
client_pk.withUnsafeBytes { client_pkPtr in
flutter_sodium.crypto_kx_server_session_keys(rxPtr, txPtr, server_pkPtr, server_skPtr, client_pkPtr)
}
}
}
}
}
用相应的方法调用
SODIUM_EXPORT
int crypto_kx_client_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES],
unsigned char tx[crypto_kx_SESSIONKEYBYTES],
const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES],
const unsigned char client_sk[crypto_kx_SECRETKEYBYTES],
const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES])
__attribute__ ((warn_unused_result));
(我知道代码并不是真正最优的 swift,但是在处理 dart 和 swift 之间的互操作性时,这就是 flutter 团队想出的方法)。
当我问这个问题时,我试图将它提炼成最简单的案例,但那个案例有一个特定的答案,这与我遇到的整体问题不同。
最佳答案
我不会使用 Data
这里——Data
表示“原始”字节的无类型集合,但是 crypto_generichash_keygen
想要一个指向类型化内存的可变指针。 UnsafeMutablePointer<T>
的原因withUnsafeMutableBytes
的变体被弃用的原因是它在非类型化内存上提供的抽象从根本上是错误的。
在 Swift 中获取类型内存缓冲区的最简单方法是使用 Array
:
var k = [UInt8](repeating: 0, count: crypto_generichash_keybytes())
flutter_sodium.crypto_generichash_keygen(&k)
您始终可以将生成的缓冲区转换为 Data
事后说 Data(k)
的值(value).
另一种选择是使用 UnsafeMutableBufferPointer
:
let k = UnsafeMutableBufferPointer<UInt8>.allocate(capacity: crypto_generichash_keybytes())
defer {
k.deallocate()
}
flutter_sodium.crypto_generichash_keygen(k.baseAddress!)
// Now use the buffer `k` – just make sure you finish using it before the end of
// the scope when `deallocate()` gets called!
不同于Array
,这避免了在传递给 C API 之前必须用零预填充结果缓冲区,但这可能并不重要。但就像Array
, 你可以把这样的缓冲区变成 Data
只说Data(k)
.
对于您收到 Data
的情况来自某些外部源的值并需要将其作为类型化指针传递给 API,最简单和最安全的选择是在通过说 Array(someData)
传递之前将其转换为数组。 .
例如:
let args = call.arguments as! NSDictionary
let server_pk = (args["server_pk"] as! FlutterStandardTypedData).data
let server_sk = (args["server_sk"] as! FlutterStandardTypedData).data
let client_pk = (args["client_pk"] as! FlutterStandardTypedData).data
var rx = [UInt8](repeating: 0, count: flutter_sodium.crypto_kx_sessionkeybytes())
var tx = [UInt8](repeating: 0, count: flutter_sodium.crypto_kx_sessionkeybytes())
flutter_sodium.crypto_kx_server_session_keys(
&rx, &tx, Array(server_pk), Array(server_sk), Array(client_pk)
)
你可能可以使用withUnsafeBytes
并调用bindMemory
在底层指针上,但我不鼓励它,因为它改变了底层内存的类型,这可能会微妙地影响共享该内存的任何其他 Swift 代码的健全性,因为您正在从它下面切换类型。
关于swift - 在 swift 5 中使用 UnsafeMutableBytes 更新代码以避免弃用警告时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55384250/
我们已经有一个使用 AnyEvent 的库。它在内部使用 AnyEvent,并最终返回一个值(同步 - 不使用回调)。有什么方法可以将这个库与 Mojolicious 一起使用吗? 它的作用如下: #
我想从 XSD 文件生成带有 JAXB 的 Java 类。 问题是,我总是得到一些像这样的类(删除了命名空间): public static class Action { @X
我有一个关于 html 输入标签或 primefaces p:input 的问题。为什么光标总是自动跳转到输入字段。我的页面高度很高,因此您需要向下滚动。输入字段位于页面末尾,光标自动跳转(加载)到页
我今天在考虑面向对象设计,我想知道是否应该避免 if 语句。我的想法是,在任何需要 if 语句的情况下,您都可以简单地创建两个实现相同方法的对象。这两个方法实现只是原始 if 语句的两个可能的分支。
String graphNameUsed = graphName.getName(); if (graphType.equals("All") || graphType.equals(
我有一张友谊 table CREATE TABLE IF NOT EXISTS `friendList` ( `id` int(10) NOT NULL, `id_friend` int(10
上下文 Debian 64。Core 2 二人组。 摆弄循环。我使用了同一循环的不同变体,但我希望尽可能避免条件分支。 但是,即使我认为它也很难被击败。 我考虑过 SSE 或位移位,但它仍然需要跳转(
我最近在 Java 中创建了一个方法来获取字符串的排列,但是当字符串太长时它会抛出这个错误:java.lang.OutOfMemoryError: Java heap space我确信该方法是有效的,
我正在使用 (C++) 库,其中需要使用流初始化对象。库提供的示例代码使用此代码: // Declare the input stream HfstInputStream *in = NULL; tr
我有一个 SQL 查询,我在 WHERE 子句中使用子查询。然后我需要再次使用相同的子查询将其与不同的列进行比较。 我假设没有办法在子查询之外访问“emp_education_list li”? 我猜
我了解到在 GUI 线程上不允许进行网络操作。对我来说还可以。但是为什么在 Dialog 按钮点击回调上使用这段代码仍然会产生 NetworkOnMainThreadException ? new T
有没有办法避免在函数重定向中使用 if 和硬编码字符串,想法是接收一个字符串并调用适当的函数,可能使用模板/元编程.. #include #include void account() {
我正在尝试避免客户端出现 TIME_WAIT。我连接然后设置 O_NONBLOCK 和 SO_REUSEADDR。我调用 read 直到它返回 0。当 read 返回 0 时,errno 也为 0。我
我正在开发 C++ Qt 应用程序。为了在应用程序或其连接的设备出现故障时帮助用户,程序导出所有内部设置并将它们存储在一个普通文件(目前为 csv)中。然后将此文件发送到公司(例如通过邮件)。 为避免
我有一组具有公共(public)父类(super class)的 POJO。这些存储在 superclass 类型的二维数组中。现在,我想从数组中获取一个对象并使用子类 的方法。这意味着我必须将它们转
在我的代码中,当 List 为 null 时,我通常使用这种方法来避免 for 语句中的 NullPointerException: if (myList != null && myList.size
我正在尝试避免客户端出现 TIME_WAIT。我连接然后设置 O_NONBLOCK 和 SO_REUSEADDR。我调用 read 直到它返回 0。当 read 返回 0 时,errno 也为 0。我
在不支持异常的语言和/或库中,许多/几乎所有函数都会返回一个值,指示其操作成功或失败 - 最著名的例子可能是 UN*X 系统调用,例如 open( ) 或 chdir(),或一些 libc 函数。 无
我尝试按值提取行。 col1 df$col1[col1 == "A"] [1] "A" NA 当然我只想要“A”。如何避免 R 选择 NA 值?顺便说一句,我认为这种行为非常危险,因为很多人都会陷入
我想将两个向量合并到一个数据集中,并将其与函数 mutate 集成为 5 个新列到现有数据集中。这是我的示例代码: vector1% rowwise()%>% mutate(vector2|>
我是一名优秀的程序员,十分优秀!