There is a function which takes void*
After passing my vector<char*>, how do I cast it back to vector<char*> and print its content using casting in C++?
Example:
void testFunction(void* data){
//cast data back to vector<char *> and print its content
}
int main()
{
std::vector<char *> arg(1);
std::string someString = "testString";
arg[0] = (char *)someString.c_str();
testFunction(&arg);
return 0;
}
You can use a static_cast to cast a void* pointer to almost any other type of pointer. The following code works for me:
void testFunction(void* data)
{
std::vector<char*>* vecdata = static_cast<std::vector<char*>*>(data);
for (auto c : *vecdata) std::cout << c;
std::cout << std::endl;
}
Just use reinterpret_cast
vector<char*>* parg = reinterpret_cast<vector<char*>*>(data);
char* mystr = parg->at(0);
std::vector<char*>& myVec= *reinterpret_cast<std::vector<char*>*>(data);
std::cout<<myVec[0];
Well actually this worked.
Related
In CPP I use a C library, one of the method needs a const void ** as parameter.
In my class I have a property whose type is void *.
I tried to call the function by doing function(&my_property) but the compiler complained that it could not convert a void ** to a const void **.
To fix this issue I used a const cast and did function(const_cast<const void *>(&my_property)).
I try to avoid casting as much as possible and I would like to know if there is a "clean" way to do that without using a const cast.
Proper solution would be to turn my_property into const void*. Otherwise you might break a contract of function.
Replicating your situation in a simple manner, let's say you have this code:
void function(const void **p)
{
//...
}
int main()
{
void *my_property;
function(&my_property);
}
Using const_cast is safe, I don't think it's all that unclean, but you have alternatives, the best of wich would be to turn my_property into a const void*, suspecting that may not be an option, you may just use a const void* pointer to wich you would assign the original void*:
void *my_property;
const void *pp = my_property;
function(&pp);
The conversion is still there, but it's implicit.
As Quentin very accurately pointed out, this does not make a lot of sense, unless it's just to shut up the compiler.
If the library is expecting an array of arrays using a cast probably wont fix it, if you can't check the library source you can guess. A manual conversion is a safe solution.
Using new_cast_a_to_m() requires you to delete the array at some point but not the original array; struct X and the code aroud it is just for this example, new_cast_a_to_m() should work for you by itself.
#include <iostream>
struct X {
int a = 0;
};
int c_foo (X ** x){
return x[4][0].a;
}
template <typename V>
V ** new_cast_a_to_m(V * arr, size_t n){
V ** nc = new V * [n];
for(size_t i=0; i < n; i++){
nc[i] = &arr[i];
}
return nc;
}
int main(void){
X ** arr = new X * [5];
arr[4] = new X;
std::cout << "intended c_foo() -> " << c_foo(arr) << std::endl;
X * brr = new X[5];
X ** nrr = new_cast_a_to_m(brr, 5);
std::cout << "casted c_foo() -> " << c_foo(nrr) << std::endl;
delete [] nrr;
delete arr[0];
delete [] arr;
return 0;
}
I am learning C++ in order to create a custom function (user defined function is how cloudera call it) that I want to use in Hadoop Cloudera Impala SQLs. Cloudera have provided a header file that has type definitions for custom function arguments
struct AnyVal {
bool is_null;
AnyVal(bool is_null = false) : is_null(is_null) {}
};
//Integer Value
struct IntVal : public AnyVal {
int32_t val;
IntVal(int32_t val = 0) : val(val) { }
static IntVal null() {
IntVal result;
result.is_null = true;
return result;
}
}
//String Value
struct StringVal : public AnyVal {
static const int MAX_LENGTH = (1 << 30);
int len;
uint8_t* ptr;
/// Construct a StringVal from ptr/len. Note: this does not make a copy of ptr
/// so the buffer must exist as long as this StringVal does.
StringVal(uint8_t* ptr = NULL, int len = 0) : len(len), ptr(ptr) {
assert(len >= 0);
};
/// Construct a StringVal from NULL-terminated c-string. Note: this does not make a copy of ptr so the underlying string must exist as long as this StringVal does.
StringVal(const char* ptr) : len(strlen(ptr)), ptr((uint8_t*)ptr) {}
static StringVal null() {
StringVal sv;
sv.is_null = true;
return sv;
}
}
Now for a simple Add function like the one below I understood how to pass the reference of IntVal object after setting IntVal.val and it worked !
IntVal AddUdf(FunctionContext* context, const IntVal& arg1, const IntVal& arg2) {
if (arg1.is_null || arg2.is_null) return IntVal::null();
return IntVal(arg1.val + arg2.val);
}
int main() {
impala_udf::FunctionContext *FunctionContext_t ;
IntVal num1, num2 , res;
num1.val=10;
num2.val=20;
IntVal& num1_ref = num1;
IntVal& num2_ref = num2;
res = AddUdf(FunctionContext_t, num1_ref, num2_ref);
cout << "Addition Result = " << res.val << "\n";
}
But I don't know how to do similar thing for a string function as StringVal requires me to pass pointer of uint8_t type for a string? I tried below one but then received "error: cannot convert std::string to uint8_t* in assignment"*
int main() {
impala_udf::FunctionContext *FunctionContext_t ;
StringVal str , res;
string input="Hello";
str.len=input.length();
str.ptr=&input;
StringVal& arg1=str;
res = StripVowels(FunctionContext_t, str);
cout << "Result = " << (char *) res.ptr<< "\n";
}
I also tried the following but no joy. Any pointer in the right direction will be much appreciated. Thanks.
str.ptr=reinterpret_cast<uint8_t*>(&input);
String itself is not a character pointer (which is what you need), but you can get one by using the c_str function.
str.ptr=(uint8_t*)(input.c_str ());
If you want to use new-style casts you might need both a const_cast (to cast from const char * to char *) and a reinterpret_cast, depending on how str.ptr is defined.
That's because you need a pointer to c-string, and you provide a pointer to std::string. str.ptr = input.c_str() should work for you.
EDIT:
However, it seems you need a non-const pointer. In this case you need to allocate input variable yourself, like:
char input[128];
This creates a fixed size array on the stack.
But you might want to allocate it dynamically with new:
char* input = new char[size];
Also check out functions in the cstring header, you might want to use those.
You might also need to cast it to uint8_t* as described above.
Don't forget to delete[] the string later when you don't need it anymore. But since you pass it to a function, this function should probably handle this.
I am trying to implement memchr() function . my code must return a void * , so if we find the character we can change it . the problem is here . I have two approaches one approach is c_style .
void *memChr(const void *s1, int c, size_type n)
{
const char *p = (const char *)s1;
while (n--)
if (*p++== (char)c)
return (void *)--p;
return 0;
}
these approach uses c-style cast , here we send s1 as const , which is proper cause we don't want any change , and then we return p as a non const pointer to void which is again proper . any way this is old , and I want a more c++ approach. like this :
void *memChr( void *s1, int c, int n)
{
char *p = static_cast< char *>(s1);
while (n--)
if (*p++ == static_cast<char>(c))
return static_cast<void *>(p);
return 0;
}
my problem with these code is this : I cant cast a const pointer to a non const pointer .static_cast is safer than c style cast , but It makes me to use non const parameter which it is not appropriate . with standard memchr() parameters ,there is no way to be implemented with static_cast .
so which approach is better? I have just finished c++ tutorials , and I am trying to learn good coding , but I am a little confused .
You can use const_cast to cast from const to non-const pointer:
void *memChr( const char *s1, int c, int n)
{
char *p = const_cast< char *>(s1);
while (n--)
if (*p++ == static_cast<char>(c))
return static_cast<void *>(p);
return 0;
}
Basically, I'm trying to do this:
char x[] = "hello";
char* y = new char[sizeof(x)](x); // won't work.
demo
Is there a way to do this cleanly? No comments on DO NOT USE raw arrays, or raw pointers please.
Just write a function.
template<typename T, size_t N>
T* new_array(T const(&arr)[N])
{
T* p = new T[N];
std::copy(std::begin(arr), std::end(arr), p);
return p;
}
int main()
{
char x[] = "hello";
char* y = new_array(x);
}
The C way:
char* y = strdup(x);
free(y);
is possible to re-map STL class object from void* ?
#include <string>
void func(void *d)
{
std::string &s = reinterpret_cast<std::string&>(d);
}
int main()
{
std::string s = "Hi";
func(reinterpret_cast<void*>(&s));
}
Use static_cast to convert void pointers back to other pointers, just be sure to convert back to the exact same type used originally. No cast is necessary to convert to a void pointer.
This works for any pointer type, including pointers to types from the stdlib. (Technically any pointer to object type, but this is what is meant by "pointers"; other types of pointers, such as pointers to data members, require qualification.)
void func(void *d) {
std::string &s = *static_cast<std::string*>(d);
// It is more common to make s a pointer too, but I kept the reference
// that you have.
}
int main() {
std::string s = "Hi";
func(&s);
return 0;
}
I re-wrote as following,
#include<string>
void func(void *d)
{
std::string *x = static_cast<std::string*>(d);
/* since, d is pointer to address, it should be casted back to pointer
Note: no reinterpretation is required when casting from void* */
}
int main()
{
std::string s = "Hi";
func(&s); //implicit converssion, no cast required
}
You code shouldn't compile.
Change
std::string &s = reinterpret_cast<std::string&>(d);
to
std::string *s = static_cast<std::string*>(d);
EDIT:
Updated code. Use static_cast instead of reinterpret_cast
Yes, it is possible, but you are trying to cast from a pointer to void *, then to a reference. The reinterpret_cast operator only allows casting back to exactly the same type that you started with. Try this instead:
void func(void *d)
{
std::string &s = *reinterpret_cast<std::string*>(d);
}