简体   繁体   中英

How would I convert a c++ vector to a lisp vector in a 0(1) operation

I have these C bindings for the C++ vector<int> which I have wrapped in CFFI.

I know how to create vector<int> s with std_carrayTovector and convert the data back to an int pointer with std_vectorToCArray so that I can retrieve data from it in Lisp using the CFFI function MEM-AREF . I have correct defcfun s written for the below.

My question is: How to I convert the output of my defcfun for std_vectorToCArray into a Lisp vector (eg #(1 2 3) ) and make it an O(1) operation — ie all data copied at the same time.

vector_int* std_carrayTovector(int* a, size_t len) {
    vector<int>* v = new vector<int>;
    for(size_t i = 0; i < len; i++) 
        v->push_back(a[i]);
    return v;
}

int* std_vectorToCArray(vector_int* s) {
    return s->data();
}


(defcfun ("std_vectori_to_carray" %vector-int-to-c-array) :pointer 
  (s (:pointer vector-int)))

I haven't tried this, but I think the following should work. The important thing that we can use about a std::vector is that it's guaranteed to have an honest-to-god array backing. That is, & my_vector [0] points at an array of the objects of my_vector . (This won't work for eg a std::list or anything else, of course)

So all you have to do is make a function (in your C++ code) that CFFI can call which returns a pointer to the start of the vector. Presumably something like this:

extern "C"
Foo*
start_of_foo_vector (std::vector<Foo> vec)
{
    return & vec[0];
}

You'll want an extern "C" so you don't need to worry about the name mangling. Of course, you'll have to write a different function for each type (and can't use templates with the extern "C" , I don't think).

The pointer you get is valid until you next modify the vector.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM