C++ void pointer - c++

I am using an HDF5 library to read data from an HDF5 file in c++ and the call I am having problems with is the following:
status = H5Dread(
hdf5_dataset,
hdf5_datatype,
hdf5_dataspace_in_memory,
hdf5_dataspace_in_file,
H5P_DEFAULT,
buf
);
The last argument is supposed to be a void pointer, and I have a vector of floats that I want to be allocated, however when I try to pass the vector g++ gives me the following error:
error: cannot convert ‘std::vector<float, std::allocator<float> >’ to ‘void*’ for argument ‘6’ to ‘herr_t H5Dread(hid_t, hid_t, hid_t, hid_t, hid_t, void*)’
Is there any way that I can write directly to the vector without having to allocate the memory twice?

As std::vector guarantees the data is stored in contiguous memory, you can convert a vector to a pointer like so:
std::vector<float> myFloats;
void *ptr = static_cast<void*>(&myFloats[0]); // or &myFloats.front()
Edit: if you are writing to it without calling push_back, make sure you resize enough space first!

Given a std::vector<float>, you can obtain a pointer to the contiguous buffer of floats thus:
std::vector<float> v;
fillMyVectorSomehow(v);
float* buffer = &v[0]; // <---
You could cast this to void* and pass it through.

Related

Is there a way to fill a vector using an array?

I'm trying to fill a vector with integers from an array I have but when I check the contents of the vector all the values are zero.
I'm using vector.push_back() to try and fill the vector so it will be in the same order as the array as I needed it ordered in a specific way.
unsigned char* buffer = new unsigned char[size];
std::vector<unsigned char> *data = new std::vector<unsigned char>(size);
fread(buffer, sizeof(unsigned char), size, f);
for(int transfer = 0; transfer < size; transfer += 1){
std::cout << buffer[transfer];
data->push_back(buffer[transfer]);
std::cout << int(data->at(transfer));
}
fclose(f);
When I print the output I can see that the values aren't zero when they're coming from the buffer array but they are when I read from the data vector. Here is some example output φ0$0.
std::vector has a constructor for this purpose:
std::vector<unsigned char> data(buffer, buffer + size);
newing a vector almost always should be avoided.
Live
The overload of the constructor of std::vector that you are using takes the number of elements to initialize the vector with and initializes these (to 0 in this case).
After the line
std::vector<unsigned char> *data = new std::vector<unsigned char>(size);
*data therefore contains already size elements set to zero.
Then with data->push_back(...) you are adding additional elements after these size elements. You are not overwriting the previous ones.
Either use
std::vector<unsigned char> *data = new std::vector<unsigned char>();
to default-initialize an empty vector, or use
(*data)[transfer] = ...
to set the elements at the given location.
Furthermore your program has undefined behavior if the fread reads less than size bytes into the array. You need to check the number of bytes read from its return value and you are not allowed to access any elements beyond that in data, because you never initialized it.
You can initialize it to zero with:
unsigned char* buffer = new unsigned char[size]{};
If you want to write C++, don't use C library functions like fread, use the facilities provided by <fstream>, i.e. std::ifstream and std::ofstream instead.
Similarly there is no need for dynamic memory allocation here. Declare variables with automatic storage:
unsigned char buffer[size]{};
std::vector<unsigned char> data(size);
and the rest of the syntax also simplifies:
data[transfer] = ...
Finally, as mentioned in the other answer, there is a constructor for std::vector that will perform the whole copy loop for you. Note however that my argument about undefined behavior still applies when using that.
Defining data as automatic array as in
unsigned char buffer[size]{};
works only if size is a compile-time constant. If it is not, then this part of my advice does not apply. However there is no real need to use arrays at all in any case. You can initialize a std::vector of proper size (compile-time constant or not) and provide that as buffer via its .data() method, which returns a pointer to the underlying (continuous) storage:
std::vector<unsigned char> buffer(size);
fread(buffer.data(), sizeof(unsigned char), buffer.size(), f);
You don't need a separate buffer or any dynamic allocation in your code. You can create the std::vector with the desired size and then read from the file directly into the vector. The std::vector::data member function returns a pointer to the vector's underlying array that you can pass to the fread() function
std::vector<unsigned char> vec(size);
fread(vec.data(), sizeof(unsigned char), size, f);
Ideally you'll also check the return value from fread() to know how many elements were read.

Passing std::vector<std::string> as array of C-style strings (char**)

I'd like to pass a vector of std::strings to OpenGL as array of C-style null terminated character arrays (const char**).
void glTransformFeedbackVaryings(GLuint program,
GLsizei count,
const char **varyings,
GLenum bufferMode);
Is it possible?
First use std::string's .c_str() function to map them to const char*'s.
std::vector<const char*> c_strs;
std::transform(std::begin(strings), std::end(strings),
std::back_inserter(c_strs), std::mem_fn(&std::string::c_str));
Then pass it to your function via the .data() member of vector:
glTransformFeedbackVaryings( ... , c_strs.size(), c_strs.data(), ...);
replacing the ...'s with your other parameters. Note: I haven't compiled this code, but it should be fine (in theory.)
If space is really important to you, you can reserve space in the vector ahead of time with
c_strs.reserve(strings.size());
or after the transform with
c_strs.shrink_to_fit();
The structures are too different. A std::string contains more than just a pointer, so it won't map directly to a char**.
You will need to copy the string's c_str() value into a new std::vector. Then you can pass that new vector's .data pointer to OpenGL.
std::vector<const char*> arg( strvect.size() );
for( std:: size_t i=0; i < arg. size(); ++i)
{
arg[i] = strvect[i].c_str();
}
Then use &arg[0].
std::vector<const char*> arr;
for(auto&& str:vec)
arr.push_back(str.c_str());
foo(...,arr.data(),...);
the above, if vec is your vector of std::string, will call foo with a char const**.
This char const** will be valid while both vec and arr are valid.
Removing const is possible if your api actually will obey const but does not support it by a const_cast at any number of spots (ie, if you have a legacy API that wants an actual char**, you can const_cast the data() call to that I suspect).

Passing an [out] array to C++ function

I have a C++\CLI managed class method that takes an out array. I want to pass this out array to the underlying C++ function that takes a vector< char >&. This C++ functions fills the array with values.
bool MyLib::GetBits([Out] array<unsigned char>^ %bits)
{
MyCppClass->GetBits(bits); // ????
// ERROR: C2664: cannot convert from 'cli::array<Type> ^' to 'std::vector<_Ty> &'
}
'GetBits' is declared as MyCppClass::GetBits(vector<char> &bits);
Have you any reason to expect that array<unsigned char>^ %bits can be converted to vector<char> &bits?
You can try to modify MyCppClass, adding a member that returns a reference to a static vector. In GetBits you can clear it, and iterate through bits adding the chars to it. You may also find Marshaling in C++ useful.

How to cast vector<unsigned char> to char*

I have a buffer like this:
vector<unsigned char> buf
How can I cast it to char*?
If I do:
(char *)buf
I get this error:
/home/richard/Desktop/richard/client/src/main.cc:102: error: invalid cast from type ‘std::vector<unsigned char, std::allocator<unsigned char> >’ to type ‘char*’
For those wondering why I am trying to do this. I need to pass the buffer to this function:
n_sent = sendto(sk,(char *)buf,(int)size,0,(struct sockaddr*) &server,sizeof(server));
And it only accepts char*.
reinterpret_cast<char*> (&buf[0]);
The vector guarantees that its elements occupy contiguous memory. So the "data" you seek is actually the address of the first element (beware of vector <bool>, this trick will fail with it). Also, why isn't your buffer vector<char> so that you don't need to reinterpret_cast?
Update for C++11
reinterpret_cast<char*>(buf.data());
reinterpret_cast<char*>(buf.data());
Try
(char *)(&buf[0])
or another, more C++ cast. But also tell us what you're using this for. It may be a bad idea.
It's very unlikely that you want to cast vector<unsigned char> to unsigned char *, but you can get a a valid pointer like this:
vector<unsigned char> v;
unsigned char *p = &*v.begin();
That strange expression will give you the pointer to the start of the internal allocated array created by the vector. If you modify the vector at all it may no longer be valid.
The reason for the redundant looking &* is that the * is really operator * on the iterator returned by v.begin(). That returns a reference to the first char of the array which you can then take the address of with &.

Ncurses User Pointer

I'm trying to learn ncurses, and I'm reading the terrific guide here, but the example at user pointers does not compile. I get this error when I try to compile.
menu.cpp: In function 'int main()':
menu.cpp:44: error: invalid conversion from 'void (*)(char*)' to 'void*'
menu.cpp:44: error: initializing argument 2 of 'int set_item_userptr(ITEM*, void*)'
menu.cpp:70: error: invalid conversion from 'void*' to 'void (*)(char*)'
Also, you probably need to add cstdlib and cstring for that to compile with strlen and calloc.
I don't know much about void pointers, so some help fixing the example would be very appreciated.
Thanks
From reading the manual page:
#include <menu.h>
int set_item_userptr(ITEM *item, void *userptr);
void *item_userptr(const ITEM *item);
DESCRIPTION
Every menu item has a field that can be used to hold application-specific data (that is, the menu-driver code leaves it alone). These functions get and set that field.
userptr is user-specific data that you should supply to set_item_userptr(). If you don't want to supply any data, you should supply NULL. Looks like you are calling set_item_userptr() with a pointer to a function as its second argument. It is not guaranteed that you can convert a function-pointer to void * and back portably, either in C or in C++ (C++ requires a cast when converting a void * to any other pointer type). Without knowing what you are trying to do, if you really need to pass a function pointer, you should cast it to the appropriate type:
int ret = set_item_userptr(item, reinterpret_cast<void *>(ptr));
void (*pf)(char*);
pf = reinterpret_cast<void (*)(char *)>(item_userptr(item));
but it's not guaranteed to work. You should do something else, like having a struct that contains the function pointer, and passing a pointer to the struct to set_item_userptr().
You are using a C++ compiler, so you will need to do:
set_item_userptr(my_items[i], (void *)func);
and again,
p = (void*)item_userptr(cur);