ASP.NET web app calling Delphi DLL on IIS webserver, locks up when returning PChar string

前端 未结 3 1204
無奈伤痛
無奈伤痛 2021-01-13 19:43

Works fine if I don\'t return anything, or I return an integer. But if I try to return a PChar, ie..

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


        
相关标签:
3条回答
  • 2021-01-13 20:05

    try to enable 32-bit applications in application pool advanced settings :

    enter image description here

    0 讨论(0)
  • 2021-01-13 20:09

    You cannot return a string like that, the string is local to the function and will be freed as soon as he function returns leaving the returned PChar pointing to an invalid location.

    you need to pass in a pointer to be filled within the DLL, dynamically create the string and free it back in the c# code or create a static buffer in yout DLL and return that.

    By far the safest way is to pass a pointer into the function ie

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

    you should set MaxLength to the sixe of the buffer before calling your dll so that the dll can check there is enough space for the data to be returned.

    0 讨论(0)
  • 2021-01-13 20:22

    Dampsquid's analysis is correct so I will not repeat that. However, I prefer a different solution that I feel to be more elegant. My preferred solution for such a problem is to use Delphi Widestring which is a BSTR.

    On the Delphi side you write it like this:

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

    And on the C# side you do it like this:

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

    And that's it. Because both parties use the same COM allocator for the memory allocation, it all just works.

    Update 1

    @NoPyGod interestingly points out that this code fails with a runtime error. Having looked into this I feel it to be a problem at the Delphi end. For example, if we leave the C# code as it is and use the following, then the errors are resolved:

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

    It would seem that Delphi return values of type WideString are not handled as they should be. Out parameters and var parameters are handled as would be expected. I don't know why return values fail in this way.

    Update 2

    It turns out that the Delphi ABI for WideString return values is not compatible with Microsoft tools. You should not use WideString as a return type, instead return it via an out parameter. For more details see Why can a WideString not be used as a function return value for interop?

    0 讨论(0)
提交回复
热议问题