Passing an [out] array to C++ function - c++

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.

Related

Conversion error when passing vector of type uint8_t to std::fill() in C++

I am using the below code snippet to pass vector of type "uint8_t" to std::fill()
size_t actual_size = 10;
std::vector<uint8_t> response;
std::fill(response.begin(), response.end() + actual_size, 0);
But i am getting the below warnings.
message : see reference to function template instantiation 'void std::fill<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<_Ty>>>,int>(const _FwdIt,const _FwdIt,const int &)' being compiled
with
[
_Ty=uint8_t,
_FwdIt=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<uint8_t>>>
]
warning C4244: '=': conversion from 'const _Ty' to 'unsigned char', possible loss of data
with
[
_Ty=int
]
How to resolve this warning.
The reason you are getting the warning is because when filling 0(an int) to a vector<uint8_t>, you are implicitly converting an int to an uint8_t, which can potentially have data loss if the original int is not in the valid range of uint8_t.
To solve it, you can either create a uint8_t directly, or manually cast the int to uint8_t.
Also, when you do:
std::fill(vec.begin(), vec.end() + some_size, some_value)
You are literally filling elements pass the end iterator, without resizing the vector, which is likely not what you wanted.
Instead, you should use fill_n to specify the number of element to fill, and use back_inserter to push it to the vector:
std::fill_n(std::back_inserter(vec), some_size, some_value);
Or you can simply initialize the vector with the appropriate data filled:
std::vector<std::uint8_t> vec(some_size, some_value);
Or even zero initialize them, since you were going to assign them to 0s:
std::vector<std::uint8_t> vec(some_size);

C++ convert std::string to char

I have following scenario:
struct MyStruct
{
char name[25];
char address[12];
}
Somewhere::SomeMethod(std::shared_ptr<SomeArgumentClass> args)
{
// GetName() and GetAddress() both return std::strings
::MyStruct newValue = {args->GetName(), args->GetAddress()};
// add newValue to some structure that needs to have chars
}
Error:
error C2440: 'initializing' : cannot convert from 'std::string' to 'char'
error C2440: 'initializing' : cannot convert from 'std::string' to 'char'
I am not able to get my std::string converted to a char.
Thanks a lot!
Firstly, your terminology is incorrect. You don't want to convert to char, which is a single character. I realise that the error message claims you're trying to convert to char, but that's because your incorrect code has confused the compiler into thinking you're trying to initialise individual elements of the array name. Be wary of the specifics of an error message when you write the wrong code, because the compiler cannot read your mind — it can only go off of what you've written!
In reality you want to copy the characters inside your std::string, into the array of char, that is your member.
Like so:
Somewhere::SomeMethod(std::shared_ptr<SomeArgumentClass> args)
{
const auto& name = args->GetName();
const auto& address = args->GetAddress();
::MyStruct newValue;
std::copy(std::begin(name), std::end(name), &newValue.name[0]);
std::copy(std::begin(address), std::end(address), &newValue.address[0]);
// add newValue to some structure that needs to have chars
}
But you need to add bounds checking too. To do that, roughly I might consider replacing each std::copy call with something like:
std::copy_n(
&name[0],
std::min(name.size(), sizeof(newValue.name)),
&newValue.name[0]
);
You'll also need some null termination depending on how many characters were copied.
Generally though the salient point is that you need to actually copy those characters because there is no one-step way to do it. It stems in part from how arrays can't be assigned-to, but also from the fact that their dimensions are part of the type which makes things more complicated.
If this seems like a pain in the arse, that's because it is — ideally you would stick with std::string across the board because it's far superior, and was specifically introduced to make it easier to handle arrays of char. You can still pass a const char* (or char*!) pointing to the string's data into a C API. Of course if ::MyStruct itself is a third-party C type, you have no choice but to do it the hard way.

Unable to create SymmetricKey

First of all version of Botan I'm using is Botan-1.10.9
And I'm writing a managed wrapper in Visual C++
Following this example, I'm trying to create a SymmetricKey from the hash of a string so I can pass it into the fe1_encrypt method of the FPE module
Signature of fe1_encrypt is
BigInt FPE::fe1_encrypt(const BigInt &n, const BigInt &X, const SymmetricKey &key, const std::vector<byte> &tweak)
I want the value I pass into the key parameter to be hash of the plaintext (not possibility to decrypt) So really I don't care about it being a SymmetricKey, just need that type because the method requires it as a parameter.
But in their example they have passed the SymmetricKey their hash method that returns an std:vector
However there is no constructor for SymmetricKey that takes this type.
Anyone have any ideas?
EDIT: I tried this with no luck
std::vector<byte> re = SHA_1(plaintextAsString);
Botan::OctetString key(re, re.size());
ERROR
Error 15 error C2664: 'Botan::OctetString::OctetString(Botan::RandomNumberGenerator &,size_t)' : cannot convert parameter 1 from 'std::vector<_Ty>' to 'Botan::RandomNumberGenerator &'
In the documentation, SymmetricKey (which is just a typedef for OctetString) can take a byte array and length as constructor. Alternatively, you can encode the key as a hex string. If you already have the key as std::vector<byte>, then this should suffice:
std::vector<byte> keybytes;
// ...fill the vector...
SymmetricKey key( keybytes.data(), keybytes.size() );
Later versions of Botan define another constructor OctetString (const std::vector<byte> &in).

cannot convert from 'const char *' to 'char *' for std::string::c_str

This gives the error: cannot convert from 'const char *' to 'char *'.
class Mock
{
public:
...
static void func(char **result)
{
*result = (resultsI++)->c_str();
}
static std::vector<std::string> results;
static std::vector<std::string>::iterator resultsI;
};
std::vector<std::string> Mock::results;
std::vector<std::string>::iterator Mock::resultsI;
How can I validly get rid of this error without changing the interface to the function func? The implementer of this interface:
void (func*)(char **result)
forgot to use const char** in the signature. I can't change it.
Remember this is a mock and I'm only used in my unit tests.
Try:
*result = &(*resultsI++)[0];
Although this isn't guaranteed to work prior to C++11 it is known to be OK on most or all current compilers.
The danger is that if the function tries to change the length of the string, you could get some nasty errors. Changing individual characters should be OK.
In test code, and if you are certain that the user of the interface isn't going to mutate the char*, maybe you could use a const_cast?
That assumes the caller doesn't take ownership of the char *; if that is the case, then you should make a copy.
If you're absolutely certain that the interface function will not modify the string, you can use
*result = const_cast<char *>((resultsI++)->c_str());
to remove constness.
Otherwise, another option is to switch from using std::vector<std::string> to std::vector<std::vector<char>> but then you'll have to make sure you properly null terminate the strings.

C++ void pointer

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.