- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在将应用程序从(目标-)C移植到Swift,但必须使用用C编写的第三方框架。有一些不兼容项,如typedef,解释为int,但必须作为uint等传递到框架的函数。因此,为了避免在整个swift应用程序中持续执行强制转换操作,我决定将C头文件传输给swift,使所有类型都在一个地方,因为我需要它们。
我几乎能转移一切,克服了很多障碍,但这一个:
C头定义了一个结构,其中包含一个uint64变量等。此结构用于将数据作为指针传输到回调函数。回调函数接受一个void指针作为参数,我必须用unsafemutablepointer操作将其强制转换为结构的类型(或者头的另一个结构,如果合适的话)。只要我使用C头中的原始结构(导入时由swift自动转换),所有的转换和内存访问就可以正常工作。
然而,在swift中手动复制结构并不是“字节匹配”。
让我向您展示一个这种情况的简化示例:
在capiheader.h文件中有
typedef struct{
uint32_t var01;
uint64_t var02;
uint8_t arr[2];
}MyStruct, *MyStructPtr;
struct MyStruct{
var01: UInt32
var02: UInt64
arr: (UInt8, UInt8)
}
typealias MyStruct = (
var01: UInt32,
var02: UInt64,
arr: (UInt8, UInt8)
)
struct MyStruct{
var01: UInt32
reserved: UInt16
var02: UInt32
arr: (UInt8, UInt8)
}
struct MyStruct{
var01: UInt32
var02: (UInt32, UInt32)
arr: (UInt8, UInt8)
}
int16_t setHandlers(MessageHandlerProc messageHandler);
typedef void (*messageHandlerProc)(unsigned int id, unsigned int messageType, void *messageArgument);
typedef struct {
uint16_t revision;
uint16_t client;
uint16_t cmd;
int16_t parameter;
int32_t value;
uint64_t time;
uint8_t stats[8];
uint16_t compoundValueOld;
int16_t axis[6];
uint16_t address;
uint32_t compoundValueNew;
} DeviceState, *DeviceStatePtr;
let myMessageHandler : MessageHandlerProc = { (deviceID : UInt32, msgType : UInt32, var msgArgPtr : UnsafeMutablePointer<Void>) -> Void in
...
}
let state = (UnsafeMutablePointer<MyDeviceState>(msgArgPtr)).memory
...
print(state.time)
print(state.stats.0)
...
最佳答案
这是在阅读了你最新的问题并进行了更多的实验之后,我对我之前的答案的更新。我认为问题在于导入的C结构和您在swift中手动实现的结构之间的对齐不一致。该问题可以通过使用c helper函数从void指针中获取c结构的实例来解决,正如昨天建议的那样,该实例随后可以转换为手动实现的swift结构。
在创建了一个看起来像
typedef struct
{
uint16_t revision;
uint16_t client;
uint16_t cmd;
int16_t parameter;
int32_t value;
uint64_t time;
uint8_t stats[8];
uint16_t compoundValueOld;
} APIStruct;
struct MyStruct
{
init( _apis : APIStruct)
{
revision = _apis.revision
client = _apis.client
cmd = _apis.cmd
parameter = _apis.parameter
value = _apis.value
time = _apis.time
stats = _apis.stats
compoundValueOld = _apis.compoundValueOld
}
var revision : UInt16
var client : UInt16
var cmd : UInt16
var parameter : Int16
var value : Int32
var time : UInt64
var stats : (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8);
var compoundValueOld : UInt16
}
#pragma pack(2)
func swiftCallBackVoid( p: UnsafeMutablePointer<Void> )
{
...
let _locMS:MyStruct = (UnsafeMutablePointer<MyStruct>(p)).memory
...
}
let _locMS:MyStruct = MyStruct(_apis: (UnsafeMutablePointer<APIStruct>(p)).memory)
https://github.com/omniprog/xcode-samples
// This typealias isn't really necessary, just a convenience
typealias APIStructPtr = UnsafeMutablePointer<APIStruct>
struct MyStructUnsafe
{
init( _p : APIStructPtr )
{
pAPIStruct = _p
}
var time: UInt64 {
get {
return pAPIStruct.memory.time
}
set( newVal ) {
pAPIStruct.memory.time = newVal
}
}
var pAPIStruct: APIStructPtr
}
func swiftCallBackVoid( p: UnsafeMutablePointer<Void> )
{
...
var _myUnsafe : MyStructUnsafe = MyStructUnsafe(_p: APIStructPtr(p))
...
_myUnsafe.time = 9876543210 // this change is visible in C code!
...
}
关于objective-c - Swift转换C的uint64_t与使用自己的UInt64类型不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33424316/
我有以下代码 unsigned int headerbytes = 0U; headerbytes = (unsigned int*)strtoull(packet_space->header
我有这段无法编译的代码: public struct MyStruct { private fixed uint myUints[32]; public uint[] MyUints
在 Go 中,从函数返回哪个更有效:返回 uint 还是返回 *uint? 该函数在 cpu 密集型库的内部 for 循环中调用。 最佳答案 一般来说,只要效率是个问题,您就应该运行基准测试。 让我们
int 加上 unsigned int 返回一个 unsigned int。应该这样吗? 考虑这段代码: #include #include #include class test {
我正在尝试从可通过 URL 访问的内容中初始化一个字符串: actualresponse.response = String(contentsOfURL: url, usedEncoding: NSU
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 提供事实和引用来回答它. 1年前关闭。 Improve this
我从函数 Swift 得到类型为 UnsafeMutablePointer 的结果 我可以把它转换到UInt吗? ? 最佳答案 只需使用memory 属性来访问底层数据。 let ptr: Unsaf
我深入了解了 List并发现了以下代码: public T this[int index] { get { // Following trick can red
我在 this page on bit twiddling 的帮助下编写了这个函数: uint16_t *decode(uint64_t instr) { // decode instr (thi
我正在从微 Controller 读取两个寄存器。一个具有 4 位 MSB(前 4 位有一些其他内容),另一个具有 8 位 LSB。我想将其转换为一个 12 位 uint(准确地说是 16 位)。到目
要演示的示例代码: public int FindComplement(int num) { //uint mask = ~0; //<-- error CS0031 //
$ rustc --test mapAsMapKey.rs mapAsMapKey.rs:18:43: 18:52 error: mismatched types: expected `fn@(&&@
一般问题:我有一个很大的二维点空间,里面稀疏地分布着点。把它想象成一 block 撒满黑点的白色大 Canvas 。我必须多次迭代和搜索这些点。 Canvas (点空间)可能很大,接近极限int 的值
假设我们只是调用一个普通数字,数字会启动什么。 uint256 plainNumber 我明白它是零。但是我要问的是,有没有办法检测该数字是由编译器还是用户变量设置的。例如... uint256 pl
我试图在 leetcode.com ( https://leetcode.com/problems/number-of-1-bits/ ) 上解决一个简单的问题,我遇到了一个奇怪的行为,这可能是我缺乏
uint number = 0x418 in bits : 0000010000011000 uint number1 = 0x8041 in bits: 1000000001000001 uint
我如何在 C# 中生成具有某个最大值的伪随机 uint? (不需要最低限度。)似乎有很多问题要求完全随机,但没有上限。 澄清:此上限可能大于 int.MaxValue,因此仅强制转换 Random.N
我已经用私有(private)数据成员围绕 ulong 编写了一个简单的包装器。我希望能够将包装器转换为 ulong 以检索数据。我希望强制转换为 uint 并丢失数据是非法的,因此我没有编写对 ui
哪些是“Uint”变量?就是有“Uint8”、“Uint16”等…… 但是它们是什么? 现在我有一些时间使用 C++,但我从来不需要使用这些变量并引起我的好奇。 提前致谢。 最佳答案 uint 不是标
我有一个 native 方法,它需要一个指针来写出一个双字(uint)。 现在我需要从 (Int) 指针中获取实际的 uint 值,但是 Marshal 类只有方便的方法来读取(有符号)整数。 如何从
我是一名优秀的程序员,十分优秀!