C# - calling ext. DLL function containing Delphi "variant record" parameter

Posted by CaldonCZE on Stack Overflow See other posts from Stack Overflow or by CaldonCZE
Published on 2010-05-29T22:49:26Z Indexed on 2010/05/29 22:52 UTC
Read the original article Hit count: 275

Filed under:
|
|

Hello,

In external (Delphi-created) DLL I've got the following function that I need to call from C# application.

function ReadMsg(handle: longword; var Msg: TRxMsg): longword; stdcall; external 'MyDll.dll' name 'ReadMsg';

The "TRxMsg" type is variant record, defined as follows:

TRxMsg = record
    case TypeMsg: byte of
        1: (accept, mask: longword);
        2: (SN: string[6]);
        3: (rx_rate, tx_rate: word);
        4: (rx_status, tx_status, ctl0, ctl1, rflg: byte);
end;

In order to call the function from C#, I declared auxiliary structure "my9Bytes" containing array of bytes and defined that it should be marshalled as 9 bytes long array (which is exactly the size of the Delphi record).

private struct my9Bytes {
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 9)]
    public byte[] data;
}

Then I declared the imported "ReadMsg" function, using the "my9bytes" struct.

[DllImport("MyDll.dll")]
private static extern uint ReadMsg(uint handle, ref my9Bytes myMsg);

I can call the function with no problem... Then I need to create structure corresponding to the original "TRxMsg" variant record and convert my auxiliary "myMsg" array into this structure.

I don't know any C# equivalent of Delphi variant array, so I used inheritance and created the following classes.

public abstract class TRxMsg {
    public byte typeMsg;
}
public class TRxMsgAcceptMask:TRxMsg {
    public uint accept, mask;
    //...
}
public class TRxMsgSN:TRxMsg {
    public string SN;
    //...
}
public class TRxMsgMRate:TRxMsg {
    public ushort rx_rate, tx_rate;
    //...
}
public class TRxMsgStatus:TRxMsg {
    public byte rx_status, tx_status, ctl0, ctl1, rflg;
    //...
}

Finally I create the appropriate object and initialize it with values manually converted from "myMsg" array (I used BitConverter for this).

This does work fine, this solution seems to me a little too complicated, and that it should be possible to do this somehow more directly, without the auxiliary "my9bytes" structures or the inheritance and manual converting of individual values. So I'd like to ask you for a suggestions for the best way to do this.

Thanks a lot!

© Stack Overflow or respective owner

Related posts about c#

Related posts about delphi