Swift:将未初始化的C结构传递给导入的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中,我创建了一个类,该类将封装结构,并与在其上运行的其他
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
}
}