1

I have a C++ API function that is called by Install Shield via InstallScript:

SQLHELPER_API LPCSTR GetAvailableAppName(LPCSTR appNameP)
{
    //return "this works just fine";
    std::string newAppName = "I work, maybe?";
    LPCSTR returnVal = newAppName.c_str();
    return returnVal;
}

The only thing that returns is an empty string. If I just return passed in variable "appNameP" it returns that just fine as well.

My main issue is that I need to pass in a LPCSTR and perform some string operation on it.

TruthOf42
  • 2,017
  • 4
  • 23
  • 38

1 Answers1

4

A LPCSTR is the same as const char *.

Passing a C-style string like that to a function call is fine.

Returning a pointer to a local function variable is not fine, because this local variable doesn´t exist anymore after the function ends. As soon as you´re using the pointer in main (or whereever the function was called), it points to a memory which doesn´t belong to you anymore, and the value may have changed already.

There are several possibilites, each with a downside:

  1. Using only memory you got as parameter (eg. appNameP, because this has to be something from outside and will still exist after the function ends). Downside: You need to pass something fitting for that purpose => the function signature or at least the requirements for the parameters changes, and you´ve to check/change how it is called.

  2. Allocating something with new. Downside: Somewhere later, outside, delete[] have to be called.

  3. Returning something like std::string. Downside: As in #1, the function signature changes, and you´ve to change how it is called.

If InstallShield calls this function itself:

What InstallShield expects you to do should be somewhere in the documentation.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
deviantfan
  • 11,268
  • 3
  • 32
  • 49
  • 1
    Another option is to declare a static object inside the function, so that it doesn't go out of scope when the function returns. For instance: `static std::string newAppName;` `newAppName = std::string("New ") + appNameP;` `return newAppName.c_str();` – Dan Korn May 29 '15 at 22:01
  • @DanKorn Bad idea if your function is called from an foreign code, not controlled by you. a) Calling the function multiple times, saving every returned pointer, and then start using the data, will not work. b) Multiple threads... – deviantfan May 29 '15 at 22:04
  • Yes, that option has its drawbacks, as do the others. It is still an option nevertheless. As for multiple threads, there's absolutely nothing preventing a pointer to a char buffer owned by another thread being passed to the function in the first place. But it's highly unlikely that a function such as this in an InstallShield installer will be called from a separate thread anyway. – Dan Korn May 29 '15 at 23:33
  • That said, though, your option "A" is generally considered the safest way to handle something like this in C. (Many Windows API functions work this way.) In C++, answer "C" should be safe in most cases. – Dan Korn May 29 '15 at 23:35