Native structure:
struct MailBox { __time32_t time; // receive time int sender; // mail sender (login) char from[64]; // mail sender (name) int to; // mail recipient char subject[128]; // mail sumbect int readed; // readed flag char* __ptr32 body; // pointer to mail body int bodylen; // mail body length short build_min; // minimum build short build_max; // maximum build int reserved; // reserved }; C # structure I wrote
[StructLayout(LayoutKind.Sequential, Pack = 1)] public struct NMailBox { internal UInt32 time; // receive time internal Int32 sender; // mail sender (login) [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] internal string from; // mail sender (name) internal Int32 to; // mail recipient [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] internal string subject; // mail sumbect internal Int32 readed; // readed flag internal Int32 body; // readed flag internal Int32 bodylen; // mail body length internal short build_min; // minimum build internal short build_max; // maximum build internal Int32 reserved; // reserved } Class for accessing data structure
public class MailBox : BaseModel<NMailBox>, IDisposable { /// <summary> /// Receive time /// </summary> public DateTime Time { get { return native.time.ToDateTime(); } set { native.time = value.ToUInt(); } } /// <summary> /// Mail sender (login) /// </summary> public Int32 Sender { get { return native.sender; } set { native.sender = value; } } /// <summary> /// Mail sender (name) /// </summary> public string From { get { return native.from; } set { native.from = value.CorrectString(64); } } /// <summary> /// Mail recipient /// </summary> public Int32 To { get { return native.to; } set { native.to = value; } } /// <summary> /// Mail sumbect /// </summary> public string Subject { get { return native.subject; } set { native.subject = value.CorrectString(128); } } /// <summary> /// Readed flag /// </summary> public Int32 Readed { get { return native.readed; } set { native.readed = value; } } public string Body { get { return Marshal.PtrToStringAnsi(native.body, native.bodylen); } set { if (native.body != IntPtr.Zero) { BodyFree(); if (native.body != IntPtr.Zero) throw new Exception(nameof(native.body)); } native.body = Marshal.StringToHGlobalAnsi(value); native.bodylen = value.Length; } } /// <summary> /// Minimum build /// </summary> public short BuildMin { get { return native.build_min; } set { native.build_min = value; } } /// <summary> /// Maximum build /// </summary> public short BuildMax { get { return native.build_max; } set { native.build_max = value; } } /// <summary> /// Reserved /// </summary> public Int32 Reserved { get { return native.reserved; } } private void BodyFree() { if (native.body != IntPtr.Zero) { var pointer = native.body; Marshal.FreeHGlobal(pointer); native.bodylen = 0; } } public void Dispose() { BodyFree(); } } The structure is used in a native function with the following signature.
virtual int __stdcall MailSend(const MailBox* mail,const int *logins)=0; The delegate I wrote to her
[UnmanagedFunctionPointer(CallingConvention.StdCall)] protected delegate ResultCode MailSendDelegate(IntPtr Obj, ref NMailBox mail, [In] int[] logins); The problem is that when I call a naive function and pass it a previously prepared structure, I get AccessViolationException
The size of the structure is customized, put SizeConst does not help
Obviously nakosyachil with the field 'Body', others should be normal. I run on x64 maybe it’s necessary to work with char __ptr32 on x64 in a special way, I don’t know for sure. At run time, the pointer is 64 bit. Perhaps when the native function accepts this pointer, it cuts it to 32 bits and the link becomes broken. Expert opinion would be how to beat a mistake?
