Преобразование станд.:: перечислите к дружественному типу C

Что самый изящный путь состоит в том, чтобы возвратить a std::list объект от общей функции lib (реализованный кодом C++) потребителю C? Я знаю для std::vector, мы можем возвратить адрес 1-го элемента вектора и сделать, чтобы потребитель рассматривал его как массив, но станд.:: список реализован как связанные литии.

7
задан theactiveactor 18 January 2010 в 16:38
поделиться

6 ответов

Копировать STD :: Список на std :: vector и вернуть адрес первого элемента, как вы уже упоминалось.

(Конечно, это может означать, что вы не хотите использовать STD :: Список в первую очередь.)

(это решение предполагает, что доступ к объекту Владелец Библиотекой C ++ - если это не так, вам может потребоваться рассмотреть возможность рассмотрения памяти из вашего C-кода и передавать указатель в библиотеку C ++ для копирования данных.)

9
ответ дан 6 December 2019 в 09:19
поделиться

всегда можно сделать копию:

list<int> lst;
int *arr = new int[lst.size()];
copy(lst.begin(),lst.end(),arr);
5
ответ дан 6 December 2019 в 09:19
поделиться

Если вы хотите, чтобы клиентский код манипулировал списком, вам нужно будет определить тип C типа:

struct Node
{
  int foo;
  float bar;
  // more data

  struct Node* next;
};

и вернуть указатель на заголовок списка:

struct Node* getData();

Что, по сути, означает, что вам нужно будет скопировать содержимое вашего std::list в структуру данных списка C типа, если вы хотите, чтобы клиентский код манипулировал списком.

Иначе вы можете скопировать содержимое вашего std::list в смежный блок памяти, вернуть этот блок вызывающему абоненту, но в этом случае ответственность за освобождение памяти лежит на вызывающем абоненте. Возвращение массива также означает, что очистка памяти должна быть произведена с помощью функции, совместимой с функцией, которую вы использовали для выделения блока: ваша реализация, скорее всего, будет использовать malloc, а не new для выделения этого блока, чтобы в дальнейшем вызывающий абонент мог использовать free на блоке.

2
ответ дан 6 December 2019 в 09:19
поделиться
sqlcmd -E -S SERVER\INSTANCE -Q "sp_databases"
-121--1506612-
EXEC sp_databases

или

SELECT NAME FROM sys.sysdatabases

или

EXEC sp_msForEachDB 'PRINT ''?''';
-121--1506613-

Единственный способ - вернуть пустоту * в объект. Затем предоставьте набор функций, которые принимают void * и манипулируют списком в коде C++.

Изменить:

Для тех, которые идут Ehhh.

std::list<int>  plop;
void* getPlopList()
{
    retutn &plop;
}

void appendToCPPList(void* list,int val)
{
    static_cast<std::list<int>*>(list)->push_back(val);
} 
// Dont forget to declare the functions extern "C"
2
ответ дан 6 December 2019 в 09:19
поделиться

Попробуйте что-нибудь подобное, не нужно std::copy, если не хотите его использовать:

std::list<int> aList;
alist.push_back(1);
alist.push_back(2);
alist.push_back(3);

std::vector<int> aVector(alist.begin(), alist.end());

cFunction(&aVector[0], aVector.size());
2
ответ дан 6 December 2019 в 09:19
поделиться

Вы можете получить итератор или список и заполнить вектор с ним:

std::list<Node> nodes;
// .. fill nodes
std::vector<node> nodeVector;
std::copy(nodes.begin(); nodes.end(); std::back_inserter(nodeVector));

, а затем вы можете работать с ним, как и с вектором, с которым вы знакомы.

0
ответ дан 6 December 2019 в 09:19
поделиться