我正在尝试通过 P/Invoke 使用 C# 代码中的 btrieve API 从 Btrieve (v6.15) 数据库中读取记录。
我已经设法读取记录,但是在阅读时会裁剪字符串的最后一个字符。如果我增加数据结构中的字符串大小,那么字符串会被正确读取,但这次下一个变量没有被正确读取。
这里可能有什么问题?
Btrieve 函数声明:
[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;
}
这些是来自 Btreive 数据库管理器的列的大小:
- 有符号整数,2 个字节
- 字符串,15 个字节
- 有符号整数,2 个字节
- 字符串,15 个字节
- 有符号整数,2 个字节
- 浮点数,8 个字节
编码:
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);
}
编辑:将字符串更改为 char 数组(感谢weismat的回答)解决了这个问题。快乐的!
[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;
}