将结构数组从c ++传递给swift

时间:2015-07-19 00:37:10

标签: c++ ios swift

我正在尝试从c ++代码返回结构数组到swift代码。

Swift代码:

var DB_HOST = process.env.DB_HOST;
var DB_USER = process.env.DB_USER;
var DB_PASS = process.env.DB_PASS;
var DB_NAME = process.env.DB_NAME;

C ++代码:

struct CPoint {
    let x: CDouble
    let y: CDouble
}

struct CStruct {
    let p1: CPoint
    let d: CDouble
    let p2: CPoint
    let i: CInt
}

func get_structs() {

    let cnt = ... //Getting size from c++ code
    var buf = [CStruct](count: cnt, repeatedValue: CStruct(p1: CPoint(x: 0, y: 0), d: 0, p2: CPoint(x: 0, y: 0), i: 0))
    let addr = UnsafeMutableBufferPointer(start: &buf, count: buf.count).baseAddress
    get_structs_c(addr)

    for cstruct in buf {
        //First cstruct is OK. Next are corrupted.
    }
}

代码很简单,但结果是损坏的值保存到typedef struct Point { double x; double y; } typedef struct Struct { Point p1; double d; Point p2; int i; } void get_structs_c(void *buf) { Struct * structs = (Struct *) buf; const std::vector<const Struct *> vec = ... // getting values no matter from where for (int i = 0; i < vec.size(); i++) { const Struct * s = vec.at(i); structs[i] = Struct{ s->p1, s->d, s->p2, s->i}; } }

但是,如果我从bufi中移除CStruct字段,则会返回正确的值,或者如果我从{{1}更改Struct的类型}和iCIntint,然后也会返回正确的值。所以,可能是CDouble桥接的一些问题。

我检查了Doubleint的大小,看起来是44个字节。

感谢任何帮助,提前谢谢!

UPD 1:只有当struct的大小与8个字节成比例时才能正常工作。

UPD 2 我检查了内存寻址,发现swift的CStruct告诉了

Struct

的大小为 44 字节,BUT&amp; struct [1] - &amp; struct [0] = 48

如果以更坏的方式重新排序结构字段:

sizeof

然后它自动对齐,struct CStruct { let p1: CPoint let d: CDouble let p2: CPoint let i: CInt } 给出大小为48,它可以正常工作。

这种默认不兼容是否正常?

1 个答案:

答案 0 :(得分:1)

您的get_structs_c函数本质上是危险的,因为您没有传入缓冲区的大小,因此这是一个缓冲区溢出漏洞!你真正需要的是这样的签名:

 struct StructList {
    Struct* items;
    size_t size;
 };

 StructList* CreateAndTransferOwnershipFromC();

或者:

 size_t CopyFromC(Struct* output_buffer, size_t buffer_size);

这里最可能发生的是你的C ++和Swift版本之间的大小不匹配,其中一些缓冲区没有被填充或你正在超出缓冲区。

如果失败,您可能会遇到alignment问题。这里更安全(但可能效率更低)的解决方案是在二进制编码字符串中序列化/反序列化数据,例如使用protocol buffers,可以更容易地保证两端的二进制兼容性。否则,您可能需要使用其中一个GCC compiler directives进行对齐/打包以确保其正确无误。