2016-12-09 7 views
0

Название не совсем отражает суть проблемы.Ошибка компиляции при попытке возврата PChar или OleVariant для UDF

У меня есть функция UDF, которая возвращает PChar.

function AccountDescription(sAccountId: PChar) : PChar; stdcall; 

Это работало нормально, но я понял, что хочу вернуть # N/A, если accountId не был найден.

Я обнаружил CVErr (xlErrNA) и изменил подпись, чтобы вернуть OleVariant. Но теперь я получаю [Ошибка] Несовместимые типы: «OleVariant» и «PAnsiChar».

Я не мог найти информацию о том, как решить эту проблему, поэтому я считаю, что мое понимание проблемы не должно быть правильным.

Я попытался просто передать строку, которая скомпилировала, но произвела ошибку времени выполнения «Недопустимый тип варианта».

Полный код:

function AccountDescription(sAccountId: PChar): OleVariant; stdcall; 
var 
    strResult: string; 
    strPChar : PChar; 
begin 

    try 
     strResult:= repo.GetAccount(sAccountId).Description; 
     strPChar := strAlloc(length(strResult)+1) ; 
     StrPCopy(strPChar, strResult) ; 
     Result := strPChar; 
    except 
     Result := CVErr(xlErrNA); 
    end; 

end; 

Примечание: Является ли первенствует ответственность за уничтожение строки или в том, что мой очистки? Должен ли я создавать копию или я должен просто возвращать указатель на существующую строку. После ввода текста я чувствую, что должен возвращать указатель.

Обновление: В этом примере был удален какой-то нерелевантный код.

Теперь с помощью:

function AccountDescription(sAccountId: PChar): OleVariant; stdcall; 
var 
    strResult: string; 
begin 

    try 
     Result := PChar(repo.GetAccount(sAccountId).Description);    
    except 
     Result := CVErr(xlErrNA); 
    end; 

end; 
+0

Таким образом, моя текущая надстройка уже имеет утечку памяти. Когда я переключился между созданием копии PChar и Результат: = PChar (repo.GetAccount (sAccountId) .Description); У меня такой же объем утечки памяти. Поэтому у меня возникают проблемы в других местах, когда дело доходит до утечки памяти. –

+0

Я проследил утечку памяти и исправил ее и повторно протестировал. Теперь я вижу, что я пропущу память, сделав копию. Когда я переключаюсь на PChar (.... Описание), я прекращаю утечку памяти. Описание происходит из репо, которое находится в памяти. –

+0

Все еще не может понять, как вернуть строку или ошибку. –

ответ

1

Вам не нужно PChar бросок, вы можете назначить String непосредственно к OleVariant (он будет преобразован в RTL в BSTR, что приемник будет свободным, когда сделано используя его):

Result := repo.GetAccount(sAccountId).Description;  

Что касается сообщений об ошибке, у вас есть жизнеспособный CVErr() функции в вашем коде Delphi? В VB CVErr() возвращает Variant типа Error (varError в Delphi), содержащий код ошибки (xlErrNA is 2042). Delphi имеет функцию VarAsError() для этой же цели:

Result := VarAsError(2042); 
+0

Итак, у меня были плохие тестовые данные. Я думал, что успешно возвращаю строку, но у меня был объект nil, который генерировал исключение и пытался вернуть CVErr (xlErrNa). Это точка отказа. Это от стороннего инструмента add-in-express. Но я также попробовал VarAsError (xlErrNa), но это не удалось. Отладчик подтвердил, что xlErrNa - 2042 из Excel2000.pas. Я думаю, проблема в том, что я использую функцию Excel Register, и я не могу указать вариант как возвращаемый тип. Регистрация ("AccountDescription", "CC"). –

+0

В дополнительной документации он использует TypeLibrary для указания UDF, но надстройка пытается зарегистрировать только UDF, если рабочие книги соответствуют нашим критериям, иначе в этом сеансе UDF не будут регистрироваться. Поэтому мы используем команду ExecuteExcel4Macro для загрузки UDF по запросу, но я думаю, что этот метод может быть ограничен. –