Swift:将未初始化的C结构传递给导入的C函数

Swift:将未初始化的C结构传递给导入的C函数,c,macos,pointers,struct,swift,C,Macos,Pointers,Struct,Swift,我知道,但这不是同一件事——传递一个指针以使用分配进行初始化 我正在与具有以下结构定义的C库接口: typedef struct myStruct { unsigned char var [50]; } myStruct; 有一个函数可以向其传递结构的地址-通常基于堆栈而不是堆,因此: myStruct mine; initMyStruct(&mine); 这将初始化结构的内容-调用者不知道内存的内部格式,因此混淆 在Swift中,我创建了一个类,该类将封装结构,并与在其上运行的其他

我知道,但这不是同一件事——传递一个指针以使用分配进行初始化

我正在与具有以下结构定义的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>)
CInt initMyStruct(str:CMutablePointer)
它并没有传递一个指针来由C库分配,这似乎是一个更常见的要求,并且在别处得到了回答

Swift目前也不支持固定大小的数组

我看不出如何满足结构的初始化要求,也无法让斯威夫特认为这将通过调用来实现


非常感谢您的帮助

我不知道initMyStruct内部发生了什么。。。但假设它是一个函数,它将要复制到字段var

我从来没有用过斯威夫特。。。但是在这个代码中,你可以将你的结构作为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);
}
#包括
typedef struct myStruct{unsigned char var[50];}myStruct;
void initMyStruct(myStruct*mine,char*ini)
{
int i=0;
做
{
mine->var[i]=(无符号字符)ini[i];
}而(ini[i++]);
}
类MyClass
{
公众:
myStruct街;
MyClass(字符*参数)
{
initMyStruct(&st,参数);
}
};
int main()
{
MyClass c(“Hakuna Matata!”);
printf(“%s\n”,c.st.var);
}
如果它使用一些cstring函数,可能会导致一些问题,因为指针是无符号的char*,而不是char*。

这是怎么回事

var mine : UnsafePointer<myStruct> = nil
initMyStrict(&mine)
var-mine:UnsafePointer=nil
initMyStrict(和我的)

我对一个C库也有同样的问题,我在苹果的论坛上问过这个问题。到目前为止还没有决议

为了在不修改原始C库的情况下解决这个问题,我在bridgeing.C/.h中创建了Create/Destroy函数

桥接

typedef struct myStruct { unsigned char var [50]; } myStruct;
myStruct * CreateMyStruct();
void DestroyMyStruct(myStruct **s);
void DoSomething(myStruct *s);
B.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)
{
    // ...
}
斯威夫特

var mine : UnsafePointer<myStruct> = CreateMyStruct();
DoSomething(mine);
DestroyMyStruct(&mine);
var-mine:UnsafePointer=CreateMyStruct();
DoSomething(我的);
破坏我的结构(矿山);

这并没有利用ARC,但至少它在不修改原始库的情况下解决了问题。

首先,让我们定义用于测试的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;
    }
}
然而,我们必须以某种方式初始化它。每个结构都有一个默认初始值设定项

var my_s: my_struct = my_struct(buffer: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
请注意,在这种情况下,
buffer[10]
已被转换为Swift作为
10元组

现在我们可以称之为:

my_struct_init(&my_s)
print("Buffer: \(my_s.buffer)") // Buffer: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
但是,结构越复杂,使用默认初始值设定项就越困难

二,。堆上的结构

这类似于在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()
var my\u s\u pointer=unsafemeutablepointer.allocate(容量:1)
打印(“缓冲区:\(我的缓冲区)”//Buffer:(一些随机值)
my_struct_init(my_s_指针)
打印(“Buffer:\(my\u s\u pointer.memory.Buffer)”//Buffer:(0,1,2,3,4,5,6,7,8,9)
my_s_指针。解除分配()
结合两种方法

以下函数将初始化任何结构:

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)
func initStruct()->S{
让struct_pointer=UnsafeMutablePointer.allocate(容量:1)
让struct\u memory=struct\u pointer.pointee
struct_pointer.dealoate()
返回结构内存
}
var my_s:my_struct=initStruct()
my_struct_init(&my_s)

信不信由你,你可以像Swift结构一样初始化C结构。Xcode甚至可以为您自动完成成员名称

在这种特殊情况下

var when = timespec(tv_sec:0, tv_nsec:0)
设置为历元时,将设置

这是一个神奇的初始值设定项,它可以为您提供任何空白结构:

func blankof<T>(type:T.Type) -> T {
    var ptr = UnsafePointer<T>.alloc(sizeof(T))
    var val = ptr.memory
    ptr.destroy()
    return val
}
自Swift 1.2版(Xcode 6.3 beta版)起, 导入的C结构现在在Swift中有一个默认的初始化器,它将结构的所有字段初始化为零

就你而言:

class MyClass {

    var mine = myStruct() // <-- Initializes all elements to zero

    init() {
        initMyStruct(&mine) // <-- No error anymore because `mine` is initialized
    }
}
class-MyClass{

var mine=myStruct()//您能用一些伪信息初始化它,然后稍后再覆盖它吗?这就是全部问题-我不知道它想要什么语法(如果有的话)作为
无符号字符[50]的初始化
。似乎没有什么是可以接受的。如果我不能初始化它,我想知道一种方法,告诉它忽略未初始化的按引用传递。我尝试了编译器选项,但没有任何效果。谢谢帮助。你真的需要使用initMyStruct吗?initMyStruct中有什么?@nightshade内部是什么并不重要,重要的是其他的C库函数——内部状态数据。事实上,我知道它被绑定到一个联合,所以50字节只是分配了不同的需求的足够存储,这取决于代码后面发生的事情。但是,对于SWIFT具有语义的问题来说,这并不重要。在C++或Obj-C类中包装结构可能是一个愚弄Swift编译器将其初始化的解决方案,但这是一个抽象层,我不想使用。如果是这样,为什么不用C++/Obj-C编写整个解决方案,并允许将其导入Swift?这似乎不是重点,但它可能反映了编译器的当前状态。您是否尝试过添加defa那么结构中的ult构造函数呢?当你声明一个变量时,也许swift会调用它。如果错误持续存在,也许你可以将字段初始化为一些随机值,然后用initstruct修复它们…或者调用initstruct f
var when = blankof(timespec)
class MyClass {

    var mine = myStruct() // <-- Initializes all elements to zero

    init() {
        initMyStruct(&mine) // <-- No error anymore because `mine` is initialized
    }
}