2015-05-29 3 views
1

У меня есть функция C++ API, который вызывается с помощью Install Shield InstallScript:Как передать LPCSTR функции C++ преобразовать в строку и вернуть LPCSTR?

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

Единственное, что возвращает это пустая строка. Если я просто вернусь в переменной «appNameP», он вернет это и отлично.

Моя основная проблема заключается в том, что мне нужно передать в LPCSTR и выполнить на нем некоторую операцию с строкой.

+1

В вакууме я бы сказал, что они хотят, чтобы вы вернули строковый литерал здесь –

ответ

4

A LPCSTR - это то же самое, что и const char *.

Передача строки типа C, подобной этому, вызову функции в порядке.

Возврат указателя на локальную переменную функции не является точным, поскольку эта локальная переменная больше не существует после завершения функции. Как только вы используете указатель в main (или независимо от того, какая функция была вызвана), он указывает на память, которая больше не принадлежит вам, и значение может быть уже изменено.

Есть несколько possibilites, каждый с оборотной стороной:

  1. Используя только памятью вы получили в качестве параметра (. Например appNameP, потому что это должно быть что-то извне, и по-прежнему будет существовать после того, как функция заканчивается) , Недостаток: вам нужно передать что-то подходящее для этой цели => подпись функции или, по крайней мере, требования к изменениям параметров, и вы должны проверить/изменить способ ее вызова.

  2. Выделять что-то с помощью new. Даунсайд: Где-то позже, снаружи, delete[] должны быть вызваны.

  3. Возвращение чего-то вроде std::string. Недостаток: как и в # 1, меняется сигнатура функции, и вы должны изменить способ ее вызова.

Если InstallShield называет саму эту функцию:

Что InstallShield ожидает, что вы делаете, должно быть где-то в документации.

+1

Другой вариант - объявить статический объект внутри функции, чтобы он не выходил за пределы области видимости при возврате функции. Например: 'static std :: string newAppName;' 'newAppName = std :: string (" New ") + appNameP;' 'return newAppName.c_str();' –

+0

@DanKorn Плохая идея, если ваша функция вызывается из иностранный код, который не контролируется вами. a) Вызов функции несколько раз, сохранение каждого возвращаемого указателя и последующее использование данных не будут работать. b) Несколько потоков ... – deviantfan

+0

Да, этот вариант имеет свои недостатки, как и другие. Тем не менее, это вариант. Что касается нескольких потоков, нет ничего, что помешало бы указателю на буфер символов, принадлежащий другому потоку, передаваться функции в первую очередь. Но очень маловероятно, что такая функция, например, в инсталляторе InstallShield, будет вызываться из отдельного потока в любом случае. –

Смежные вопросы