Boost logo

Boost Users :

Subject: [Boost-users] Using boost with 'c' level interfaces ?
From: avib369 . (avibahra_at_[hidden])
Date: 2013-06-06 13:07:20


I can not find any solution where a 'c' api
can update/modify a std::vector

Passing a std::vector<int>/std::vector<double> to a
'c' or fortran api function, that _reads_, works like a charm.

However we are out of luck, if we need the 'c' api, to
populate the array. When passing a std::vector will
'kind of' work. But you can never use any of the following

      // 1/ size()
      // 2/ empty()
      // 3/ begin()/ end()/ rbegin()/rend()
      // 4/ push_back()
      // 5/ pop_back()

 You have to separately carry the size of the vector, in
 order to use it. You then just end up using it like a 'c' array.
 I thought there may have been way of updating the vectors
 begin/finish after the api call. But there does not appear to
 any way to do this.

 One solution would be to use 'c' array when calling the
interface, and then copy to a std::vector.
However this would degrade performance, when dealing large data sets.

 Is there any boost libraries/containers that are applicable or that
 can handle this issue ? It must have similar properties to a vector,
 like contiguous memory ?

I have included a sample program below, to demonstrate.

Before resorting back to 'c' array I was wondering
if any one else has come across this problem ?

Ta,
  Avi

=============================================================

#include <vector>
#include <string>
#include <string.h> // memcopy
#include <stdlib.h> // malloc
#include <iostream>
#include <ostream>

using namespace std;

void c_function_that_reads(int* array, int size_of_array)
{
   for(int i = 0; i < size_of_array; i++) cout << array[i] << ",";
   cout << "\n";
}

void c_function_that_writes(int* array, int size_of_array)
{
   for(int i = 0; i < size_of_array; i++) array[i] = i;
}

int main(){
   {
      cout << "\ncalling c_function_that_reads\n";
      vector<int> dataVec; dataVec.push_back(1); dataVec.push_back(22);
      c_function_that_reads(&dataVec[0],dataVec.size());
   }
   {
      cout << "\ncalling c_function_that_writes\n";
      int the_size = 10;
      int* int_array = (int*)malloc(the_size*sizeof(int));
      c_function_that_writes(int_array,the_size);

      // Copy into vector.
      vector<int> dataVec;
      dataVec.insert(dataVec.end(), &int_array[0], &int_array[the_size]);
      for(size_t i = 0; i < dataVec.size(); i++) { cout << dataVec[i] <<
","; }
      cout << "\n";
      free(int_array);
   }
   {
      cout << "\ncalling c_function_that_writes\n";
      int the_size = 10;
      vector<int> dataVec;
      dataVec.reserve(the_size);
      c_function_that_writes(&dataVec[0],the_size);

      cout << "dataVec.size() = " << dataVec.size() << ",
dataVec.capacity() = " << dataVec.capacity() << " dataVec.empty() = " <<
dataVec.empty() << "\n";

      cout << "for(size_t i = 0; i < dataVec.size(); i++): BROKEN\n";
      for(size_t i = 0; i < dataVec.size(); i++) { cout << dataVec[i] <<
","; }
      cout << "\n";

      cout << "for(size_t i = 0; i < the_size; i++): WORKS\n";
      for(int i = 0; i < the_size; i++) { cout << dataVec[i] << ","; }
      cout << "\n\n";

      cout << "for(vector<int>::iterator i = dataVec.begin(); i !=
dataVec.end(); i++): BROKEN\n";
      for(vector<int>::iterator i = dataVec.begin(); i != dataVec.end();
i++) { cout << (*i) << ","; }
      cout << "\n";

      dataVec.push_back(11); the_size += 1;
      // dataVec.pop_back(); the_size -= 1; // also broken
      cout << "for(size_t i = 0; i < dataVec.size(); i++): BROKEN\n";
      for(size_t i = 0; i < dataVec.size(); i++) { cout << dataVec[i] <<
","; }
      cout << "\n";

      cout << "for(size_t i = 0; i < the_size; i++): BROKEN\n";
      for(int i = 0; i < the_size; i++) { cout << dataVec[i] << ","; }
      cout << "\n\n";

      cout << "for(vector<int>::iterator i = dataVec.begin(); i !=
dataVec.end(); i++): BROKEN\n";
      for(vector<int>::iterator i = dataVec.begin(); i != dataVec.end();
i++) { cout << (*i) << ","; }
      cout << "\n";

      // Using std::vector is ok for read only access when calling a c api
function
      // *however* Using a c/fortrans api to *populate* a std::vector leads
to issues:
      //
      // The following will not work after the api call.
      // 1/ size()
      // 2/ empty()
      // 3/ begin()/ end()/ rbegin()/rend()
      // 4/ push_back()
      // 5/ pop_back()
      // 6/ will ~vector() work since that use begin()/end() ??
      // Is it worth using std::vector, since many of invariants are broken
????
      // We have to carry the length separately
   }
}



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net