Веб-приложение ASP.NET, вызывающее Delphi DLL на веб-сервере IIS, блокируется при возврате строки PChar

Хорошо работает, если я ничего не верну, или я возвращаю целое число. Но если я попытаюсь вернуть PChar, то есть ..

result := PChar('') or result:= PChar('Hello') 

Веб-приложение просто зависает, и я наблюдаю, как его количество памяти постепенно становится все выше и выше в диспетчере задач.

Странно, что DLL отлично работает на сервере отладки VStudio или через приложение C #. Единственное, о чем я могу думать, это повлияет на то, что сервер IIS работает в 64-битной Windows.

Это, похоже, не проблема совместимости, хотя, поскольку я могу успешно писать в текстовые файлы и делать другие вещи из DLL … Я просто НЕ могу вернуть строку PChar.

Пробовал использовать PWideChar, попытался вернуть «что-то» 0, попробовал все, что мог придумать. К сожалению, к сожалению.

 [DllImport("TheLib.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)] private static extern string SomeFunction(); string result = SomeFunction(); 

Дельфи:

 library TheLib; function SomeFunction() : PChar export; stdcall; begin return PChar(''); end; exports SomeFunction 

Анализ Дамскквида верен, поэтому я не буду повторять этого. Однако я предпочитаю другое решение, которое я считаю более элегантным. Мое предпочтительное решение для такой проблемы – использовать Delphi Widestring который является BSTR .

На стороне Delphi вы пишете это так:

 function SomeFunction: Widestring; stdcall; begin Result := 'Hello'; end; 

И на стороне C # вы делаете это так:

 [DllImport(@"TheLib.dll")] [return: MarshalAs(UnmanagedType.BStr)] private static extern string SomeFunction(); 

И это все. Поскольку обе стороны используют один и тот же СОМ-распределитель для распределения памяти, все это просто работает.

Обновление 1

@NoPyGod интересно указывает, что этот код выходит из строя с ошибкой во время выполнения. Взглянув на это, я чувствую, что это проблема в конце Delphi. Например, если мы оставим код C # так, как есть, и воспользуемся следующим, то ошибки будут устранены:

 function SomeFunction: PChar; stdcall; begin Result := SysAllocString(WideString('Hello')); end; 

Казалось бы, возвращаемые значения Delphi типа WideString не обрабатываются, как должно быть. Параметры вывода и параметры var обрабатываются, как и следовало ожидать. Я не знаю, почему возвратные значения терпят неудачу таким образом.

Обновление 2

Оказывается, что возвращаемые значения Delphi ABI для WideString несовместимы с инструментами Microsoft. Вы не должны использовать WideString как возвращаемый тип, а вместо этого возвращаете его через параметр out . Для получения дополнительной информации см. Почему WideString не может использоваться как возвращаемое значение функции для взаимодействия?

Вы не можете вернуть такую ​​строку, строка является локальной для функции и будет освобождена, как только функция вернется, оставив возвращенный PChar, указав на недопустимое местоположение.

вам нужно передать указатель для заполнения в DLL, динамически создать строку и освободить ее обратно в коде c # или создать статический буфер в DLL DLL и вернуть это.

Безусловно, самым безопасным способом является передача указателя на функцию, т.е.

 function SomeFunction( Buffer: PChar; MaxLength: PInteger ): wordbool; stdcall; { // fill in the buffer and set MaxLength to length of data } 

вы должны установить MaxLength в шестерку буфера перед вызовом вашей DLL, чтобы DLL могла проверить, что для возвращаемых данных достаточно места.

попробуйте включить 32-разрядные приложения в дополнительных настройках пула приложений:

введите описание изображения здесь