How can I order a Delphi short string using p / invoke?

I have a problem with a variable type from a dll that I import in C #. It is written in Object Oriented Pascal and it says it is developed with the Delphi Development Tool.

The library manual says that shortstring

is a packed array of bytes. The first byte is the length, and the next is 255 bytes with the string data I need.

So, after importing the dll in C #, I wrote:

[return: MarshalAs(UnmanagedType.LPArray)]

      

Then called a function from dll:

public static extern byte[] xxxx();

      

But I am getting the following error:

Unable to marshal "return value": invalid managed / unmanaged combination

On the other hand, I've tried the following:

[return: MarshalAs(UnmanagedType.SafeArray)]

      

This time I get the error:

SafeArray of rank 18727 passed to a method expecting an array of rank 1

Could you please tell me what I am doing wrong and first of all the right way to get the shortstring from the compiled library?

Hello

+3


source to share


1 answer


I think the cleanest way to marshal a short Delphi string is to wrap it in a structure.

[StructLayout(LayoutKind.Sequential)]
public struct DelphiShortString
{
    private byte length;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst=255)]
    private byte[] payload;

    public string Value 
    {
        get 
        { 
            return Encoding.Default.GetString(payload, 0, length); 
        }
        set 
        {
            length = (byte)Math.Min(value.Length, 255);
            payload = Encoding.Default.GetBytes(value.Substring(0, length));
        }
    }
}

      

This type is not blittable and therefore cannot be used as a function return value. If you have control over your Delphi code, you can make sure not to use short strings as return functions. However, I suspect you are not in control of it. In this case, you need the blittable version of the struct. Which will look like this:



[StructLayout(LayoutKind.Sequential)]
public unsafe struct DelphiShortString
{
    private byte length;

    private fixed byte payload[255];

    public string Value 
    {
        get 
        {
            {
                byte[] bytes = new byte[length];
                fixed (byte* ptr = payload)
                {
                    Marshal.Copy((IntPtr)ptr, bytes, 0, length);
                }
                return Encoding.Default.GetString(bytes, 0, length); 
            }
        }
        set 
        {
            byte[] bytes = Encoding.Default.GetBytes(value);
            length = (byte)Math.Min(bytes.Length, 255);
            fixed (byte* ptr = payload)
            {
                Marshal.Copy(bytes, 0, (IntPtr)ptr, length);
            }
        }
    }
}

      

This indicates bad design for a DLL to export a Delphi short string. This suggests that the author of the library did not develop it for compatibility with other compilers. This, in turn, assumes that the functions can use the standard Delphi calling convention. This is register

not supported by Microsoft tools. If my guess is correct, then this DLL cannot be used directly. You will need to write a DLL adapter that will open up a more user-friendly interface.

+8


source







All Articles