0

I have a library that I'm using where a function takes a void *, but the text I'm trying to pass is of type std::string. So I did

void CastToVoid(std::string *data)
{
    void *temp = *(static_cast<void*>(data));
}

And am using it like

            foregroundWindow = GetActiveWindowTitle();
            CastToVoid( static_cast<std::string*>(&foregroundWindow));
            Speak(&foregroundWindow); // Where speak is what takes the void*

This yields illegal indirection. Any idea why?

Turret
  • 133
  • 8
  • 1
    Does this answer your question? [How to convert a std::string to const char\* or char\*?](https://stackoverflow.com/questions/347949/how-to-convert-a-stdstring-to-const-char-or-char) – 273K Feb 16 '21 at 05:55
  • 1
    `CastToVoid` doesn't do anything and pointers are automatically converted to `void*`. So `CastToVoid` can be safely removed. Take a look at documentation for `Speak` and see what argument it actually expects. Maybe you simply _can't_ pass a string there. – Lukas-T Feb 16 '21 at 06:16

2 Answers2

1

Since your Speak(void *) function takes an untyped/void pointer, it's unclear what sort of argument it is expecting. i.e. is Speak() expecting its argument to be a pointer to a NUL-terminated byte array, or is it expecting its argument to be a pointer to a std::string object? Since void * is untyped, either one will compile, but passing in the "wrong" argument will likely cause a crash or other undefined behavior at runtime.

That said, if Speak(void *) is implemented to expect its argument to point to a std::string, then you could call it like this (as you do above):

Speak(&foregroundWindow);

or if Speak(void *) is implemented to expect its argument to be a pointer to a NUL-terminated char array, you could instead call it like this:

Speak(const_cast<void *>(foregroundWindow.c_str()));

The best approach, though would be to modify the argument-type of the Speak() method to specify the type of the pointer it takes, rather than accepting a void *, so that the compiler could flag an error when the programmer passes in an inappropriate value, rather than allowing the programming error to pass undetected and cause a runtime malfunction. So something like:

void Speak(std::string * pointerToStdString);

or better yet (if Speak() doesn't need to modify the std::string):

void Speak(const std::string * pointerToStdString);

or (if Speak() just needs the pointer-to-the-NUL-terminated-chars-array)

void Speak(const char * pointerToChars);
Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234
  • Thanks for your answer. Here is the code. ``` void Speak(void *text) { if (!eciAddText(eciHandle, text)) { printf( "eciAddText failed\n" ); } if (!eciSynthesize(eciHandle)) { printf( "eciSynthesize failed\n" ); } if (!eciSynchronize(eciHandle)) { printf( "eciSynchronize failed\n" ); } } ``` What approach would you suggest based off that? – Turret Feb 16 '21 at 06:38
  • Oh and here's the line causing a problem. void *temp = *(static_cast(data)); – Turret Feb 16 '21 at 06:52
  • Yes, that line is a problem, because the asterisk just after the `=` is trying to dereference a `void *`, which isn't a sensible thing to do. (i.e. if you dereference an `int *` that give you an `int`, which makes sense, but trying to dereference a `void *` would give you... a `void`? What is a `void`? A `void` is by definition an unknown type, so the operation isn't allowed) – Jeremy Friesner Feb 16 '21 at 06:57
  • ... and in any case, as @churill mentioned in his comment above, the entire `CastToVoid` function doesn't do anything useful, since even if it compiled and ran, all it is doing is declaring a local variable and then getting rid of that local variable when the function returns, so it has no effect on anything the program does. – Jeremy Friesner Feb 16 '21 at 06:59
  • 1
    @Turret Where did you get that code from? `eciAddText` takes a `const char*`, and removing that type information is counterproductive. (Try `Speak(foregroundWindow.c_str())`. – molbdnilo Feb 16 '21 at 08:36
  • Omg... it worked... I feel stupid... thank you. And to answer your question, it's from eci.h, for interfacing to the IBM Eloquence synthesizer. – Turret Feb 16 '21 at 15:55
0

std::string is a container object, which holds information about a string. Under the hood, it looks something like this (just for the sake of explaining),

class string {
public:
    string() {}
    
    ...
    // Other member functions.

private:
    char* pData = nullptr;
};

As you can see, the std::string itself isnt a string type (meaning std::string is not " "). So casting it to void* will result in undefined behavior.

If your goal is to pass the string data as void*, then use std::string::c_str() to get the actual string data as const char*. This way you can pass the string to the function you want.

D-RAJ
  • 3,263
  • 2
  • 6
  • 24