У меня есть эти привязки C для C ++ vector<int>
который я завернул в CFFI.
Я знаю как создать vector<int>
с std_carrayTovector
и преобразовать данные обратно в int
указатель с std_vectorToCArray
так что я могу получить данные из него в Лиспе, используя функцию CFFI MEM-AREF
, Я правильно defcfun
написано для ниже.
Мой вопрос: как я могу преобразовать вывод моего defcfun
за std_vectorToCArray
в вектор Lisp (например, #(1 2 3)
) и сделать это операцией O (1) — то есть все данные скопированы одновременно.
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)))
Я не пробовал это, но я думаю, что следующее должно работать. Важная вещь, которую мы можем использовать о std::vector
это то, что он гарантированно будет иметь честную поддержку массива. То есть, & my_vector [0]
указывает на массив объектов my_vector
, (Это не будет работать, например, для std::list
или что-нибудь еще, конечно)
Поэтому все, что вам нужно сделать, это создать функцию (в вашем коде C ++), которую CFFI может вызвать, которая возвращает указатель на начало вектора. Предположительно что-то вроде этого:
extern "C"Foo*
start_of_foo_vector (std::vector<Foo> vec)
{
return & vec[0];
}
Вы будете хотеть extern "C"
так что вам не нужно беспокоиться об искажении имени. Конечно, вам придется написать разные функции для каждого типа (и вы не можете использовать шаблоны с extern "C"
Не думаю).
Полученный вами указатель действителен до следующего изменения вектора.