我知道this answer,但这不是一回事 - 那就是传递一个指针,并通过分配进行初始化。
我与具有以下结构定义的C库接口:
typedef struct myStruct { unsigned char var [50]; } myStruct;
有一个函数可以传递结构的地址 - 通常基于堆栈而不是堆,因此:
myStruct mine;
initMyStruct(&mine);
这会初始化结构的内容 - 调用者不知道内存的内部格式,因此会混淆。
在Swift中,我创建了一个类,它将封装结构和与其他C函数接口的接口。
class MyClass {
var mine : myStruct
init() {
initMyStruct(&mine)
// Error: Variable 'self.msg' passed by reference before being initialized
}
}
我不能为我的生活弄清楚如何初始化结构,或者如果可以替代使用一个点。
mine = myStruct()
// Fails because you aren't providing the value of the member 'var'
mine = myStruct((CUnsignedChar(), CUnsignedChar(), /*... repeat to 50 */))
// Cannot find an overload for 'init' that accepts the arguments
请注意,这是将已分配的(基于堆栈的)结构的地址传递给已导入为
的函数CInt initMyStruct(str: CMutablePointer<myStruct>)
它没有传递一个由有问题的C库分配的指针,这似乎是一个更常见的要求,并在其他地方得到解答。
Swift目前也不支持固定大小的阵列。
我无法看到如何满足结构的初始化,或者让Swift认为通过电话会这样做。
任何帮助都非常感谢!
答案 0 :(得分:11)
首先,让我们定义用于测试的C代码:
typedef struct my_struct {
unsigned char buffer[10];
} my_struct;
void my_struct_init(my_struct *my_s) {
for (int i = 0; i < 10; i++) {
my_s->buffer[i] = (char) i;
}
}
在Swift中,我们有两个选择:
1。堆叠上的结构
var my_s: my_struct = ...
但是,我们必须以某种方式初始化它。每个结构都有一个默认初始值设定项
var my_s: my_struct = my_struct(buffer: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
请注意,在这种情况下,buffer[10]
已被翻译为Swift 10-tuple
。
现在我们可以致电:
my_struct_init(&my_s)
print("Buffer: \(my_s.buffer)") // Buffer: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
但是,结构越复杂,使用默认初始值设定项就越困难。
2。堆上的结构
这类似于在C:
中使用malloc
和free
var my_s_pointer = UnsafeMutablePointer<my_struct>.allocate(capacity: 1)
print("Buffer: \(my_s.buffer)") // Buffer: (some random values)
my_struct_init(my_s_pointer)
print("Buffer: \(my_s_pointer.memory.buffer)") // Buffer: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
my_s_pointer.deallocate()
结合两种方法
以下函数将初始化任何结构:
func initStruct<S>() -> S {
let struct_pointer = UnsafeMutablePointer<S>.allocate(capacity: 1)
let struct_memory = struct_pointer.pointee
struct_pointer.dealloate()
return struct_memory
}
var my_s: my_struct = initStruct()
my_struct_init(&my_s)
答案 1 :(得分:3)
信不信由你,你可以像Swift Struct一样初始化C Struct。 Xcode甚至可以为您自动填充成员名称!
在这个特殊情况下,
var when = timespec(tv_sec:0, tv_nsec:0)
将when
设置为纪元。
这是一个神奇的初始化程序,可以为您提供任何空白结构:
func blankof<T>(type:T.Type) -> T {
var ptr = UnsafePointer<T>.alloc(sizeof(T))
var val = ptr.memory
ptr.destroy()
return val
}
上面的例子是:
var when = blankof(timespec)
答案 2 :(得分:3)
从Swift 1.2(Xcode 6.3 beta)开始, 导入的C结构现在在Swift中有一个默认的初始化器,它将所有struct的字段初始化为零。
在你的情况下:
class MyClass {
var mine = myStruct() // <-- Initializes all elements to zero
init() {
initMyStruct(&mine) // <-- No error anymore because `mine` is initialized
}
}
答案 3 :(得分:2)
我对C库有同样的问题,并在Apple的论坛上提出了这个问题。到目前为止还没有决议。
要在不修改原始C库的情况下解决该问题,我在Bridging.c / .h中创建了创建/销毁函数
Bridging.h
typedef struct myStruct { unsigned char var [50]; } myStruct;
myStruct * CreateMyStruct();
void DestroyMyStruct(myStruct **s);
void DoSomething(myStruct *s);
Bridging.c
myStruct * CreateMyStruct() {
myStruct * mine = malloc(sizeof(myStruct));
if (mine)
initMyStruct(mine);
return mine;
}
void DestroyMyStruct(myStruct **s) {
if (*s)
free(*s);
*s = NULL; // set the swift variable to nil
}
void DoSomething(myStruct *s)
{
// ...
}
Example.swift
var mine : UnsafePointer<myStruct> = CreateMyStruct();
DoSomething(mine);
DestroyMyStruct(&mine);
这并没有利用ARC,但它至少在没有修改原始库的情况下解决了这个问题。
答案 4 :(得分:1)
这个怎么样
var mine : UnsafePointer<myStruct> = nil
initMyStrict(&mine)
答案 5 :(得分:0)
我不知道initMyStruct内部发生了什么......但是假设它是一个函数,它将要复制的字符串作为参数复制到字段 var
我从未使用过swift ...但是在这个代码中你可以将你的结构作为c ++类成员...
也许你可以使用这个只是封装结构的类?
#include <cstdio>
typedef struct myStruct { unsigned char var [50]; } myStruct;
void initMyStruct(myStruct *mine, char *ini)
{
int i = 0;
do
{
mine->var[i] = (unsigned char) ini[i];
} while(ini[i++]);
}
class MyClass
{
public:
myStruct st;
MyClass(char *parameter)
{
initMyStruct(&st, parameter);
}
};
int main()
{
MyClass c("Hakuna Matata!");
printf("%s\n", c.st.var);
}
如果它使用了一些cstring函数,它可能会导致一些问题,因为指针是unsigned char *而不是char * ...