Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

need help converting delphi record to C# struct and passing this struct to C dll:

type Transaction = record
  pos_id: array[0..9] of char;
  ev_type: array[0..4] of char;
  amount: array[0..14] of char;
  chip_reader_used: boolean;
  internal_magstripereader_used: boolean;
  track2data: array[0..99] of char;
  card_usage_mode: array[0..4] of char;
  receipt_directory: array[0..254] of char;
  additional_info: array[0..999] of char;
  event_number: array[0..9] of char;
  original_filingcode: array[0..19] of char;
  transaction_reasoncode: array[0..9] of char;
end;

tried following but not working:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public unsafe struct Transaction {
        public fixed byte pos_id[10];
        public fixed byte ev_type[5];
        public fixed byte amount[15];
        public bool       chip_reader_used;
        public bool       internal_magstripereader_used;
        public fixed byte track2data[100];
        public fixed byte card_usage_mode[5];
        public fixed byte receipt_directory[255];
        public fixed byte additional_info[1000];
        public fixed byte event_number[10];
        public fixed byte original_filingcode[20];
        public fixed byte transaction_reasoncode[10];
};

and C function is:

void Card_Event(struct)

C# (loaded by GetProcAddress)

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void Card_Event_Func(ref Transaction transaction);

IntPtr procAddr = GetProcAddress(_hDLL, "Card_Event");
if ( procAddr == IntPtr.Zero )
    return false;
Card_Event_Func Card_Event = (Card_Event_Func)Marshal.GetDelegateForFunctionPointer(procAddr, typeof(Card_Event_Func));
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
168 views
Welcome To Ask or Share your Answers For Others

1 Answer

You should use UnmanagedType.ByValTStr for the strings. There is no need for unsafe code here. You'll find that declaration below, using strings, is much easier to use than unsafe fixed arrays.

Note that you also need to specify single byte marshalling for the booleans. The default marshalling for bool is a 4 byte BOOL compatible with Win32 API functions.

Finally, I'm not sure why you chose to pack the record. There's no indication in the Delphi code that it is packed.

So, the final translation looks like this:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct Transaction 
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
    public string pos_id;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5)]
    public string ev_type;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 15)]
    public string amount;

    [MarshalAs(UnmanagedType.I1)]
    public bool chip_reader_used;

    [MarshalAs(UnmanagedType.I1)]
    public bool internal_magstripereader_used;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
    public string track2data;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5)]
    public string card_usage_mode;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
    public string receipt_directory;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1000)]
    public string additional_info;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
    public string event_number;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
    public string original_filingcode;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
    public string transaction_reasoncode;
};

I'm not sure that you have translation the function call correctly because you've not shown a function native code declaration of the function.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...