开发者

Converting std::list to C friendly type

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 o开发者_StackOverflowf the 1st element of the vector and have the consumer treat it as an array, but std::list is implemented as a linked lis.


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 always can make a copy:

list<int> lst;
int *arr = new int[lst.size()];
copy(lst.begin(),lst.end(),arr);


If 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.


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"


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜