What's the most elegant way to return a std::list
object from a shared lib function (implemented by C++ code) to a C consumer? I know for std::vector
, we can return the address of the 1st element of the vector and have the consumer treat it as an array, but std::list is implemented as a linked lis.
views:
218answers:
6If you want the client code to manipulate a list, you will have to define a C type like:
struct Node
{
int foo;
float bar;
// more data
struct Node* next;
};
and return a pointer to the head of the list:
struct Node* getData();
Which basically means that you will have to copy the content of your std::list
to a C like list data structure if you want the client code to manipulate a list.
Otherwise, you can copy the content of your std::list
into a contiguous memory block, return this block to the caller but in this case it's the caller responsibility to release the memory. Returning an array also means the memory clean up has to be done with a function compatible with the function you used to allocate the block: your implementation will likely use malloc
and not new
to allocate this block, so that the caller can later use free
on the block.
you always can make a copy:
list<int> lst;
int *arr = new int[lst.size()];
copy(lst.begin(),lst.end(),arr);
Copy the std::list
to a std::vector
and return the address of the first element, as you already mentioned.
(Of course, this may mean that you don't want to be using a std::list
in the first place.)
(This solution assumes that the object being accessed is owned by the C++ library -- If this isn't the case, you may need to consider allocating the memory from your C code and passing a pointer into the C++ library to copy the data.)
You can get an iterator or the list and fill a vector with it:
std::list<Node> nodes;
// .. fill nodes
std::vector<node> nodeVector;
std::copy(nodes.begin(); nodes.end(); std::back_inserter(nodeVector));
And then you can work with it just like with the vector that you are familiar with.
Try something like this, no need for a std::copy
if you don't want to use it:
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());
The only way to do it is to return a void* to the obejct. Then provide a set of functions that accept the void* and manipulate the list in the C++ code.
Edit:
For those that go 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"