English 中文(简体)
• 粉碎层变数在p/invoke的记忆中一致——
原标题:Memory alignment of struct variables for p/invoke - Strings lose the last character

我正试图通过P/Invoke使用C#代码的Btrieve(v6.15)数据库的记录。

I have managed to read records, however last character of strings are cropped while reading. If I increase the string size in my data struct then the string is read properly but this time the next variable is not read correctly.

这里可能有什么错误?

Btrieve function declaration:

        [DllImport("WBTRV32.dll", CharSet = CharSet.Ansi)]
    static extern short BTRCALL(ushort operation,
        [MarshalAs(UnmanagedType.LPArray, SizeConst = 128)] byte[] posBlk,
        [MarshalAs(UnmanagedType.Struct, SizeConst = 255)] 
        ref RecordBuffer databuffer, 
        ref int dataLength, 
        [MarshalAs(UnmanagedType.LPArray, SizeConst = 255)] char[] keyBffer, 
        ushort keyLength, ushort keyNum);

我的结构定义:

    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
    public struct RecordBuffer
    {
        public short docType;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 15)]
        public string docDescPlural;
        public short sorting;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 15)]
        public string docDescSingle;
        public short copyOtherThanSrc;
        public double defaultNotebookNo;
    }

These are the sizes for the columns, from Btreive database manager:

  1. signed int, 2 bytes
  2. string, 15 bytes
  3. signed int, 2 bytes
  4. string, 15 bytes
  5. signed int, 2 bytes
  6. float, 8 bytes

该法典:

    private void PopulateAllRecords(string fileName)
    {
        byte[] positionBlock = new byte[128];
        char[] fileNameArray = fileName.ToCharArray();

        // Open file
        RecordBuffer dataBuffer = new RecordBuffer();
        int bufferLength = System.Runtime.InteropServices.Marshal.SizeOf(dataBuffer);
        BReturnCodes status = (BReturnCodes) BTRCALL(
            BOPEN, positionBlock, ref dataBuffer, ref bufferLength, fileNameArray, 0, 0);

        if (status == BReturnCodes.NO_ERROR)
        {
            // Get first record
            dataBuffer = new RecordBuffer();
            status = (BReturnCodes) BTRCALL(
                BGETFIRST, positionBlock, ref dataBuffer, ref bufferLength, fileNameArray, 0, 0);

            if (status == BReturnCodes.NO_ERROR)
            {
                AddListViewItem(dataBuffer);
            }

            // Get subsequent records
            while (status == BReturnCodes.NO_ERROR) // BReturnCodes.END_OF_FILE or an error will occur
            {
                dataBuffer = new RecordBuffer();
                status = (BReturnCodes)BTRCALL(
                    BGETNEXT, positionBlock, ref dataBuffer, ref bufferLength, fileNameArray, 0, 0);

                if (status == BReturnCodes.NO_ERROR)
                {
                    AddListViewItem(dataBuffer);                        
                }
            }
        }
        else
        {
            MessageBox.Show("Error occured while opening file: " + status.ToString());
        }
    }

    private void AddListViewItem(RecordBuffer buffer)
    {
        ListViewItem item = new ListViewItem(buffer.docType.ToString());
        item.SubItems.Add(buffer.docDescPlural);
        item.SubItems.Add(buffer.sorting.ToString());
        item.SubItems.Add(buffer.docDescSingle);
        item.SubItems.Add(buffer.copyOtherThanSrc.ToString());
        item.SubItems.Add(buffer.defaultNotebookNo.ToString());
        listView.Items.Add(item);
    }

Edit:将扼杀物改成果园(比我们主义的答案)解决了这一问题。 幸福!

    [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
    public struct RecordBuffer
    {
        public short docType;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)]
        public char[] docDescPlural;
        public short sorting;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)]
        public char[] docDescSingle;
        public short copyOtherThanSrc;
        public double defaultNotebookNo;
    }
最佳回答

I would asume that the issue comes from the which is expected when using a C# string with p/invoke.
I have no experience with Btrieve, but it is pretty likely there is no .
Could you post the original c structure? Otherwise you need to use a byte array with a fixed length of 15 and convert it into a string afterwards.
Furthermore I would use the sizeof operator to compare the size of the structure on both ends.

问题回答

暂无回答




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签