commit b51e2b451e377bcda6b73976d65fb9a843f43bda Author: lvpeng Date: Sat Jun 6 10:07:53 2026 +0800 666 diff --git a/CSharp调用说明.md b/CSharp调用说明.md new file mode 100644 index 0000000..63f63b3 --- /dev/null +++ b/CSharp调用说明.md @@ -0,0 +1,237 @@ +# XYParser 的 C# 调用说明 + +## 1. 项目现状 + +当前工程已经是一个 **C++ 原生 DLL**,不是 .NET DLL。 +C# 调用它的推荐方式是使用 **P/Invoke**。 + +相关接口定义见: + +- [XYParserApi.h](file:///c:/Users/xyyl666/Desktop/XYParser/XYParser/XYParserApi.h#L12-L40) +- [XYParserApi.cpp](file:///c:/Users/xyyl666/Desktop/XYParser/XYParser/XYParserApi.cpp#L59-L154) + +当前主要导出函数: + +- `XYParser_CreateParser` +- `XYParser_DestroyParser` +- `XYParser_SetAdcParams` +- `XYParser_SetBypassChecksum` +- `XYParser_Feed` +- `XYParser_GetLastError` + +## 2. 使用方式 + +### 2.1 先编译 DLL + +在 Visual Studio 中打开: + +- [XYParser.sln](file:///c:/Users/xyyl666/Desktop/XYParser/XYParser/XYParser.sln) + +建议编译配置: + +- `Release | x64` + +编译后得到: + +- `XYParser.dll` + +运行 C# 程序时,需要把 `XYParser.dll` 放到: + +- C# 可执行程序同目录 +- 或系统可搜索到的 DLL 路径中 + +## 3. C# P/Invoke 声明 + +```csharp +using System; +using System.Runtime.InteropServices; + +internal static class NativeMethods +{ + private const string DllName = "XYParser.dll"; + + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr XYParser_CreateParser(byte channel_count); + + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void XYParser_DestroyParser(IntPtr handle); + + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void XYParser_SetAdcParams(IntPtr handle, double vref, double gain); + + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern void XYParser_SetBypassChecksum(IntPtr handle, int bypass); + + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern int XYParser_Feed( + IntPtr handle, + byte[] data, + UIntPtr size, + [Out] XYParserFrameSummary[] outSummaries, + int maxSummaries); + + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr XYParser_GetLastError(IntPtr handle); +} +``` + +## 4. 结构体定义 + +C++ 中的结构体定义见: + +- [XYParserFrameSummary](file:///c:/Users/xyyl666/Desktop/XYParser/XYParser/XYParserApi.h#L21-L29) + +对应的 C# 写法: + +```csharp +using System.Runtime.InteropServices; + +[StructLayout(LayoutKind.Sequential)] +public struct XYParserFrameSummary +{ + public uint frame_index; + public byte channel_count; + public byte battery; + public byte sample_count; + + // C++: double channel_values_uv[5][64] + // C#: 按一维数组接收,总长度 = 5 * 64 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5 * 64)] + public double[] channel_values_uv; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] + public byte[] trigger_types; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] + public byte[] trigger_indices; +} +``` + +## 5. 调用示例 + +```csharp +using System; +using System.IO; +using System.Runtime.InteropServices; + +class Program +{ + static void Main() + { + IntPtr handle = NativeMethods.XYParser_CreateParser(8); + if (handle == IntPtr.Zero) + { + throw new Exception("创建解析器失败"); + } + + try + { + NativeMethods.XYParser_SetAdcParams(handle, 4.5, 6.0); + NativeMethods.XYParser_SetBypassChecksum(handle, 1); + + byte[] input = File.ReadAllBytes("test.bin"); + + XYParserFrameSummary[] summaries = new XYParserFrameSummary[8]; + for (int i = 0; i < summaries.Length; i++) + { + summaries[i].channel_values_uv = new double[5 * 64]; + summaries[i].trigger_types = new byte[5]; + summaries[i].trigger_indices = new byte[5]; + } + + int count = NativeMethods.XYParser_Feed( + handle, + input, + (UIntPtr)input.Length, + summaries, + summaries.Length); + + string lastError = Marshal.PtrToStringAnsi( + NativeMethods.XYParser_GetLastError(handle)) ?? ""; + + Console.WriteLine($"解析出的帧数: {count}"); + Console.WriteLine($"最后错误: {lastError}"); + + if (count > 0) + { + double firstValue = summaries[0].channel_values_uv[0]; + Console.WriteLine($"第一帧第一个采样点第一个通道值: {firstValue}"); + } + } + finally + { + NativeMethods.XYParser_DestroyParser(handle); + } + } +} +``` + +## 6. 二维数组取值说明 + +C++ 中: + +```cpp +double channel_values_uv[5][64]; +``` + +C# 中按一维数组接收后,索引方式为: + +```csharp +double value = summary.channel_values_uv[sampleIndex * 64 + channelIndex]; +``` + +例如: + +- 第 `0` 个采样点,第 `0` 个通道:`[0 * 64 + 0]` +- 第 `1` 个采样点,第 `3` 个通道:`[1 * 64 + 3]` + +## 7. 注意事项 + +- `CallingConvention` 要使用 `Cdecl` +- `XYParser_GetLastError` 返回的是 `const char*`,需用 `Marshal.PtrToStringAnsi` +- C# 程序位数必须和 DLL 一致 +- 你当前更适合使用 `x64` +- `channel_count` 当前只支持 `8` 和 `64` + +## 8. 推荐封装方式 + +如果后续要长期在 C# 中使用,建议再包一层托管类,例如: + +```csharp +public sealed class XYParser : IDisposable +{ + private IntPtr _handle; + + public XYParser(byte channelCount) + { + _handle = NativeMethods.XYParser_CreateParser(channelCount); + if (_handle == IntPtr.Zero) + throw new InvalidOperationException("创建解析器失败"); + } + + public void SetAdcParams(double vref, double gain) + { + NativeMethods.XYParser_SetAdcParams(_handle, vref, gain); + } + + public void SetBypassChecksum(bool enabled) + { + NativeMethods.XYParser_SetBypassChecksum(_handle, enabled ? 1 : 0); + } + + public void Dispose() + { + if (_handle != IntPtr.Zero) + { + NativeMethods.XYParser_DestroyParser(_handle); + _handle = IntPtr.Zero; + } + } +} +``` + +## 9. 总结 + +- 当前工程已经能生成原生 `XYParser.dll` +- C# 不需要重写解析逻辑,直接用 `DllImport` 即可调用 +- 最关键的是函数声明匹配、结构体布局匹配、位数一致 diff --git a/XYParser/.vs/XYParser/FileContentIndex/332a0de7-d835-4415-b1be-cf475791396e.vsidx b/XYParser/.vs/XYParser/FileContentIndex/332a0de7-d835-4415-b1be-cf475791396e.vsidx new file mode 100644 index 0000000..463a0dc Binary files /dev/null and b/XYParser/.vs/XYParser/FileContentIndex/332a0de7-d835-4415-b1be-cf475791396e.vsidx differ diff --git a/XYParser/.vs/XYParser/FileContentIndex/6225afac-624d-4f54-a882-d4c4ed1136cd.vsidx b/XYParser/.vs/XYParser/FileContentIndex/6225afac-624d-4f54-a882-d4c4ed1136cd.vsidx new file mode 100644 index 0000000..4fb6efd Binary files /dev/null and b/XYParser/.vs/XYParser/FileContentIndex/6225afac-624d-4f54-a882-d4c4ed1136cd.vsidx differ diff --git a/XYParser/.vs/XYParser/FileContentIndex/6bf894f6-0520-47ea-9e65-054447e1d543.vsidx b/XYParser/.vs/XYParser/FileContentIndex/6bf894f6-0520-47ea-9e65-054447e1d543.vsidx new file mode 100644 index 0000000..3cf0eab Binary files /dev/null and b/XYParser/.vs/XYParser/FileContentIndex/6bf894f6-0520-47ea-9e65-054447e1d543.vsidx differ diff --git a/XYParser/.vs/XYParser/FileContentIndex/f94d6cf6-4de9-49c6-baeb-118cb6def7c6.vsidx b/XYParser/.vs/XYParser/FileContentIndex/f94d6cf6-4de9-49c6-baeb-118cb6def7c6.vsidx new file mode 100644 index 0000000..4bcf68f Binary files /dev/null and b/XYParser/.vs/XYParser/FileContentIndex/f94d6cf6-4de9-49c6-baeb-118cb6def7c6.vsidx differ diff --git a/XYParser/.vs/XYParser/v17/.suo b/XYParser/.vs/XYParser/v17/.suo new file mode 100644 index 0000000..2bf455a Binary files /dev/null and b/XYParser/.vs/XYParser/v17/.suo differ diff --git a/XYParser/.vs/XYParser/v17/Browse.VC.db b/XYParser/.vs/XYParser/v17/Browse.VC.db new file mode 100644 index 0000000..870c5c5 Binary files /dev/null and b/XYParser/.vs/XYParser/v17/Browse.VC.db differ diff --git a/XYParser/.vs/XYParser/v17/Browse.VC.db-shm b/XYParser/.vs/XYParser/v17/Browse.VC.db-shm new file mode 100644 index 0000000..c282009 Binary files /dev/null and b/XYParser/.vs/XYParser/v17/Browse.VC.db-shm differ diff --git a/XYParser/.vs/XYParser/v17/Browse.VC.db-wal b/XYParser/.vs/XYParser/v17/Browse.VC.db-wal new file mode 100644 index 0000000..e69de29 diff --git a/XYParser/.vs/XYParser/v17/Browse.VC.opendb b/XYParser/.vs/XYParser/v17/Browse.VC.opendb new file mode 100644 index 0000000..e69db01 Binary files /dev/null and b/XYParser/.vs/XYParser/v17/Browse.VC.opendb differ diff --git a/XYParser/.vs/XYParser/v17/DocumentLayout.backup.json b/XYParser/.vs/XYParser/v17/DocumentLayout.backup.json new file mode 100644 index 0000000..31d5e46 --- /dev/null +++ b/XYParser/.vs/XYParser/v17/DocumentLayout.backup.json @@ -0,0 +1,171 @@ +{ + "Version": 1, + "WorkspaceRootPath": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\", + "Documents": [ + { + "AbsoluteMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYParserApi.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|solutionrelative:XYParserApi.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYParserApi.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|solutionrelative:XYParserApi.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParserExample.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|solutionrelative:XYEegParserExample.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser64.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|solutionrelative:XYEegParser64.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParserCommon.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|solutionrelative:XYEegParserCommon.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser8.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|solutionrelative:XYEegParser8.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser64.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|solutionrelative:XYEegParser64.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser8.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|solutionrelative:XYEegParser8.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\dllmain.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|solutionrelative:dllmain.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + } + ], + "DocumentGroupContainers": [ + { + "Orientation": 0, + "VerticalTabListWidth": 256, + "DocumentGroups": [ + { + "DockedWidth": 200, + "SelectedChildIndex": 0, + "Children": [ + { + "$type": "Document", + "DocumentIndex": 0, + "Title": "XYParserApi.h", + "DocumentMoniker": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYParserApi.h", + "RelativeDocumentMoniker": "XYParserApi.h", + "ToolTip": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYParserApi.h", + "RelativeToolTip": "XYParserApi.h", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAA0AAAAUAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", + "WhenOpened": "2026-06-04T06:13:17.908Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 1, + "Title": "XYParserApi.cpp", + "DocumentMoniker": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYParserApi.cpp", + "RelativeDocumentMoniker": "XYParserApi.cpp", + "ToolTip": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYParserApi.cpp", + "RelativeToolTip": "XYParserApi.cpp", + "ViewState": "AgIAAH4AAAAAAAAAAADwvwAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", + "WhenOpened": "2026-06-04T06:13:04.173Z", + "EditorCaption": "" + }, + { + "$type": "Bookmark", + "Name": "ST:0:0:{aa2115a1-9712-457b-9047-dbb71ca2cdd2}" + }, + { + "$type": "Document", + "DocumentIndex": 2, + "Title": "XYEegParserExample.cpp", + "DocumentMoniker": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParserExample.cpp", + "RelativeDocumentMoniker": "XYEegParserExample.cpp", + "ToolTip": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParserExample.cpp", + "RelativeToolTip": "XYEegParserExample.cpp", + "ViewState": "AgIAAFwAAAAAAAAAAAAAAFAAAAADAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", + "WhenOpened": "2026-06-04T05:55:44.898Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 3, + "Title": "XYEegParser64.h", + "DocumentMoniker": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser64.h", + "RelativeDocumentMoniker": "XYEegParser64.h", + "ToolTip": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser64.h", + "RelativeToolTip": "XYEegParser64.h", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAQAAAAkAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", + "WhenOpened": "2026-06-04T05:51:57.408Z" + }, + { + "$type": "Document", + "DocumentIndex": 4, + "Title": "XYEegParserCommon.h", + "DocumentMoniker": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParserCommon.h", + "RelativeDocumentMoniker": "XYEegParserCommon.h", + "ToolTip": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParserCommon.h", + "RelativeToolTip": "XYEegParserCommon.h", + "ViewState": "AgIAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", + "WhenOpened": "2026-06-04T05:50:06.166Z" + }, + { + "$type": "Document", + "DocumentIndex": 7, + "Title": "XYEegParser8.h", + "DocumentMoniker": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser8.h", + "RelativeDocumentMoniker": "XYEegParser8.h", + "ToolTip": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser8.h", + "RelativeToolTip": "XYEegParser8.h", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", + "WhenOpened": "2026-06-04T05:49:55.73Z" + }, + { + "$type": "Document", + "DocumentIndex": 6, + "Title": "XYEegParser64.cpp", + "DocumentMoniker": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser64.cpp", + "RelativeDocumentMoniker": "XYEegParser64.cpp", + "ToolTip": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser64.cpp", + "RelativeToolTip": "XYEegParser64.cpp", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", + "WhenOpened": "2026-06-04T05:49:51.523Z" + }, + { + "$type": "Document", + "DocumentIndex": 5, + "Title": "XYEegParser8.cpp", + "DocumentMoniker": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser8.cpp", + "RelativeDocumentMoniker": "XYEegParser8.cpp", + "ToolTip": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser8.cpp", + "RelativeToolTip": "XYEegParser8.cpp", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", + "WhenOpened": "2026-06-04T05:49:48.717Z" + }, + { + "$type": "Document", + "DocumentIndex": 8, + "Title": "dllmain.cpp", + "DocumentMoniker": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\dllmain.cpp", + "RelativeDocumentMoniker": "dllmain.cpp", + "ToolTip": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\dllmain.cpp", + "RelativeToolTip": "dllmain.cpp", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", + "WhenOpened": "2026-06-04T03:55:05.048Z" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/XYParser/.vs/XYParser/v17/DocumentLayout.json b/XYParser/.vs/XYParser/v17/DocumentLayout.json new file mode 100644 index 0000000..c43af48 --- /dev/null +++ b/XYParser/.vs/XYParser/v17/DocumentLayout.json @@ -0,0 +1,171 @@ +{ + "Version": 1, + "WorkspaceRootPath": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\", + "Documents": [ + { + "AbsoluteMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYParserApi.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|solutionrelative:XYParserApi.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYParserApi.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|solutionrelative:XYParserApi.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParserExample.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|solutionrelative:XYEegParserExample.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser64.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|solutionrelative:XYEegParser64.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParserCommon.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|solutionrelative:XYEegParserCommon.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser8.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|solutionrelative:XYEegParser8.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser64.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|solutionrelative:XYEegParser64.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser8.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|solutionrelative:XYEegParser8.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\dllmain.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}|XYParser.vcxproj|solutionrelative:dllmain.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + } + ], + "DocumentGroupContainers": [ + { + "Orientation": 0, + "VerticalTabListWidth": 256, + "DocumentGroups": [ + { + "DockedWidth": 200, + "SelectedChildIndex": 0, + "Children": [ + { + "$type": "Document", + "DocumentIndex": 0, + "Title": "XYParserApi.h", + "DocumentMoniker": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYParserApi.h", + "RelativeDocumentMoniker": "XYParserApi.h", + "ToolTip": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYParserApi.h", + "RelativeToolTip": "XYParserApi.h", + "ViewState": "AgIAABsAAAAAAAAAAAAAACMAAAA4AAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", + "WhenOpened": "2026-06-04T06:13:17.908Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 1, + "Title": "XYParserApi.cpp", + "DocumentMoniker": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYParserApi.cpp", + "RelativeDocumentMoniker": "XYParserApi.cpp", + "ToolTip": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYParserApi.cpp", + "RelativeToolTip": "XYParserApi.cpp", + "ViewState": "AgIAAI4AAAAAAAAAAADwvwAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", + "WhenOpened": "2026-06-04T06:13:04.173Z", + "EditorCaption": "" + }, + { + "$type": "Bookmark", + "Name": "ST:0:0:{aa2115a1-9712-457b-9047-dbb71ca2cdd2}" + }, + { + "$type": "Document", + "DocumentIndex": 2, + "Title": "XYEegParserExample.cpp", + "DocumentMoniker": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParserExample.cpp", + "RelativeDocumentMoniker": "XYEegParserExample.cpp", + "ToolTip": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParserExample.cpp", + "RelativeToolTip": "XYEegParserExample.cpp", + "ViewState": "AgIAAFwAAAAAAAAAAAAAAFAAAAADAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", + "WhenOpened": "2026-06-04T05:55:44.898Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 3, + "Title": "XYEegParser64.h", + "DocumentMoniker": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser64.h", + "RelativeDocumentMoniker": "XYEegParser64.h", + "ToolTip": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser64.h", + "RelativeToolTip": "XYEegParser64.h", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAQAAAAkAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", + "WhenOpened": "2026-06-04T05:51:57.408Z" + }, + { + "$type": "Document", + "DocumentIndex": 4, + "Title": "XYEegParserCommon.h", + "DocumentMoniker": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParserCommon.h", + "RelativeDocumentMoniker": "XYEegParserCommon.h", + "ToolTip": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParserCommon.h", + "RelativeToolTip": "XYEegParserCommon.h", + "ViewState": "AgIAAMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", + "WhenOpened": "2026-06-04T05:50:06.166Z" + }, + { + "$type": "Document", + "DocumentIndex": 7, + "Title": "XYEegParser8.h", + "DocumentMoniker": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser8.h", + "RelativeDocumentMoniker": "XYEegParser8.h", + "ToolTip": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser8.h", + "RelativeToolTip": "XYEegParser8.h", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", + "WhenOpened": "2026-06-04T05:49:55.73Z" + }, + { + "$type": "Document", + "DocumentIndex": 6, + "Title": "XYEegParser64.cpp", + "DocumentMoniker": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser64.cpp", + "RelativeDocumentMoniker": "XYEegParser64.cpp", + "ToolTip": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser64.cpp", + "RelativeToolTip": "XYEegParser64.cpp", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", + "WhenOpened": "2026-06-04T05:49:51.523Z" + }, + { + "$type": "Document", + "DocumentIndex": 5, + "Title": "XYEegParser8.cpp", + "DocumentMoniker": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser8.cpp", + "RelativeDocumentMoniker": "XYEegParser8.cpp", + "ToolTip": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\XYEegParser8.cpp", + "RelativeToolTip": "XYEegParser8.cpp", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", + "WhenOpened": "2026-06-04T05:49:48.717Z" + }, + { + "$type": "Document", + "DocumentIndex": 8, + "Title": "dllmain.cpp", + "DocumentMoniker": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\dllmain.cpp", + "RelativeDocumentMoniker": "dllmain.cpp", + "ToolTip": "C:\\Users\\xyyl666\\Desktop\\XYParser\\XYParser\\dllmain.cpp", + "RelativeToolTip": "dllmain.cpp", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", + "WhenOpened": "2026-06-04T03:55:05.048Z" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/XYParser/.vs/XYParser/v17/Solution.VC.db b/XYParser/.vs/XYParser/v17/Solution.VC.db new file mode 100644 index 0000000..df9b234 Binary files /dev/null and b/XYParser/.vs/XYParser/v17/Solution.VC.db differ diff --git a/XYParser/.vs/XYParser/v17/ipch/da131652d6dd7f4a.ipch b/XYParser/.vs/XYParser/v17/ipch/da131652d6dd7f4a.ipch new file mode 100644 index 0000000..80db3be Binary files /dev/null and b/XYParser/.vs/XYParser/v17/ipch/da131652d6dd7f4a.ipch differ diff --git a/XYParser/XYEegParser64.cpp b/XYParser/XYEegParser64.cpp new file mode 100644 index 0000000..30947ec --- /dev/null +++ b/XYParser/XYEegParser64.cpp @@ -0,0 +1,2 @@ +#include "pch.h" +#include "XYEegParser64.h" diff --git a/XYParser/XYEegParser64.h b/XYParser/XYEegParser64.h new file mode 100644 index 0000000..b9423c5 --- /dev/null +++ b/XYParser/XYEegParser64.h @@ -0,0 +1,10 @@ +#pragma once + +#include "XYEegParserCommon.h" + +using XYEegFrame64 = xyparser::XYEegFrame<64>; + +class XYEegParser64 final : public xyparser::XYEegTcpParserCommon<64> { +public: + using Frame = XYEegFrame64; +}; diff --git a/XYParser/XYEegParser8.cpp b/XYParser/XYEegParser8.cpp new file mode 100644 index 0000000..c123756 --- /dev/null +++ b/XYParser/XYEegParser8.cpp @@ -0,0 +1,2 @@ +#include "pch.h" +#include "XYEegParser8.h" diff --git a/XYParser/XYEegParser8.h b/XYParser/XYEegParser8.h new file mode 100644 index 0000000..54e7f6e --- /dev/null +++ b/XYParser/XYEegParser8.h @@ -0,0 +1,10 @@ +#pragma once + +#include "XYEegParserCommon.h" + +using XYEegFrame8 = xyparser::XYEegFrame<8>; + +class XYEegParser8 final : public xyparser::XYEegTcpParserCommon<8> { +public: + using Frame = XYEegFrame8; +}; diff --git a/XYParser/XYEegParserCommon.h b/XYParser/XYEegParserCommon.h new file mode 100644 index 0000000..90c6487 --- /dev/null +++ b/XYParser/XYEegParserCommon.h @@ -0,0 +1,266 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace xyparser { + +template +struct XYEegSample { + std::array channel_values_uv{}; + std::uint8_t trigger_type = 0; + std::uint8_t trigger_index = 0; +}; + +template +struct XYEegFrame { + static constexpr std::size_t kSamplesPerFrame = 5; + + std::uint8_t header = 0; + std::uint32_t index = 0; + std::uint16_t payload_length = 0; + std::uint8_t battery = 0; + std::uint8_t channel_count = 0; + std::int16_t elevation_angle = 0; + std::int16_t rolling_angle = 0; + std::int16_t yaw_angle = 0; + std::int16_t ecg = 0; + std::int16_t blood_oxygen = 0; + std::array reserved{}; + std::array, kSamplesPerFrame> samples{}; + std::uint8_t crc = 0; + std::array tails{}; +}; + +template +class XYEegTcpParserCommon { +public: + using Frame = XYEegFrame; + + static constexpr std::uint8_t kFrameHeader = 0xAA; + static constexpr std::uint8_t kFrameTail = 0x55; + static constexpr std::size_t kSamplesPerFrame = 5; + static constexpr std::size_t kFrameHeaderLen = 1; + static constexpr std::size_t kFrameTailLen = 2; + static constexpr std::size_t kFrameTagLen = 25; + + void SetAdcParams(double vref, double gain) noexcept + { + if (vref > 0.0) { + vref_ = vref; + } + if (gain > 0.0) { + gain_ = gain; + } + } + + void SetBypassChecksum(bool bypass) noexcept + { + bypass_checksum_ = bypass; + } + + bool BypassChecksum() const noexcept + { + return bypass_checksum_; + } + + void Reset() + { + buffer_.clear(); + last_error_.clear(); + } + + const std::string &LastError() const noexcept + { + return last_error_; + } + + std::vector Feed(const std::vector &bytes) + { + return Feed(bytes.data(), bytes.size()); + } + + std::vector Feed(const std::uint8_t *data, std::size_t size) + { + std::vector frames; + if (data == nullptr || size == 0) { + return frames; + } + + buffer_.insert(buffer_.end(), data, data + size); + + while (true) { + const auto header_it = std::find(buffer_.begin(), buffer_.end(), kFrameHeader); + if (header_it == buffer_.end()) { + buffer_.clear(); + break; + } + + const std::size_t header_index = static_cast(std::distance(buffer_.begin(), header_it)); + if (buffer_.size() < header_index + 7) { + if (header_index > 0) { + buffer_.erase(buffer_.begin(), buffer_.begin() + static_cast(header_index)); + } + break; + } + + const std::uint16_t payload_length = ReadBE16(buffer_, header_index + 5); + const std::size_t total_frame_len = payload_length + kFrameTagLen + kFrameTailLen + kFrameHeaderLen; + if (buffer_.size() - header_index < total_frame_len) { + if (header_index > 0) { + buffer_.erase(buffer_.begin(), buffer_.begin() + static_cast(header_index)); + } + break; + } + + const std::size_t tail_index = header_index + payload_length + kFrameTagLen + kFrameHeaderLen; + if (tail_index + 1 >= buffer_.size() || buffer_[tail_index] != kFrameTail || buffer_[tail_index + 1] != kFrameTail) { + buffer_.erase(buffer_.begin(), buffer_.begin() + static_cast(header_index + 1)); + continue; + } + + std::vector frame_bytes( + buffer_.begin() + static_cast(header_index), + buffer_.begin() + static_cast(tail_index + 2)); + buffer_.erase(buffer_.begin(), buffer_.begin() + static_cast(tail_index + 2)); + + Frame frame; + if (TryParseFrame(frame_bytes, frame)) { + frames.push_back(frame); + } + } + + return frames; + } + +private: + static std::uint16_t ReadBE16(const std::vector &bytes, std::size_t offset) noexcept + { + return static_cast((static_cast(bytes[offset]) << 8) | + static_cast(bytes[offset + 1])); + } + + static std::uint16_t ReadLE16(const std::vector &bytes, std::size_t offset) noexcept + { + return static_cast(static_cast(bytes[offset]) | + (static_cast(bytes[offset + 1]) << 8)); + } + + static std::uint32_t ReadLE32(const std::vector &bytes, std::size_t offset) noexcept + { + return static_cast(bytes[offset]) | + (static_cast(bytes[offset + 1]) << 8) | + (static_cast(bytes[offset + 2]) << 16) | + (static_cast(bytes[offset + 3]) << 24); + } + + double ConvertAdcToUv(const std::uint8_t raw0, const std::uint8_t raw1, const std::uint8_t raw2) const noexcept + { + double value = static_cast(raw0) * 65536.0 + + static_cast(raw1) * 256.0 + + static_cast(raw2); + const double factor = vref_ / gain_ / 8388608.0 * 1000000.0; + if (value < 8388608.0) { + return value * factor; + } + return -(16777216.0 - value) * factor; + } + + bool CheckChecksum(const std::vector &frame_bytes) const noexcept + { + if (frame_bytes.size() < 4) { + return false; + } + + const std::size_t crc_index = frame_bytes.size() - 3; + std::uint8_t checksum = 0; + for (std::size_t i = 0; i < crc_index; ++i) { + checksum = static_cast(checksum + frame_bytes[i]); + } + return checksum == frame_bytes[crc_index]; + } + + bool TryParseFrame(const std::vector &frame_bytes, Frame &frame) + { + if (!bypass_checksum_ && !CheckChecksum(frame_bytes)) { + last_error_ = "checksum failed"; + return false; + } + + const std::size_t min_frame_len = kFrameHeaderLen + kFrameTagLen + kFrameTailLen; + if (frame_bytes.size() < min_frame_len) { + last_error_ = "frame too short"; + return false; + } + + const std::size_t channel_count_offset = kFrameHeaderLen + 4 + 2 + 1; + const std::uint8_t channel_count = frame_bytes[channel_count_offset]; + if (channel_count != ChannelCount) { + last_error_ = "unexpected channel count"; + return false; + } + + const std::size_t sample_bytes = ChannelCount * 3 + 2; + const std::size_t expected_frame_len = kFrameHeaderLen + kFrameTagLen + + kSamplesPerFrame * sample_bytes + kFrameTailLen; + if (frame_bytes.size() != expected_frame_len) { + last_error_ = "frame length mismatch"; + return false; + } + + std::size_t offset = 0; + frame.header = frame_bytes[offset++]; + frame.index = ReadLE32(frame_bytes, offset); + offset += 4; + frame.payload_length = ReadBE16(frame_bytes, offset); + offset += 2; + frame.battery = frame_bytes[offset++]; + frame.channel_count = frame_bytes[offset++]; + frame.elevation_angle = static_cast(ReadLE16(frame_bytes, offset)); + offset += 2; + frame.rolling_angle = static_cast(ReadLE16(frame_bytes, offset)); + offset += 2; + frame.yaw_angle = static_cast(ReadLE16(frame_bytes, offset)); + offset += 2; + frame.ecg = static_cast(ReadLE16(frame_bytes, offset)); + offset += 2; + frame.blood_oxygen = static_cast(ReadLE16(frame_bytes, offset)); + offset += 2; + + for (std::size_t i = 0; i < frame.reserved.size(); ++i) { + frame.reserved[i] = frame_bytes[offset++]; + } + + for (auto &sample : frame.samples) { + for (std::size_t channel = 0; channel < ChannelCount; ++channel) { + sample.channel_values_uv[channel] = ConvertAdcToUv( + frame_bytes[offset], + frame_bytes[offset + 1], + frame_bytes[offset + 2]); + offset += 3; + } + sample.trigger_type = frame_bytes[offset++]; + sample.trigger_index = frame_bytes[offset++]; + } + + frame.crc = frame_bytes[offset++]; + frame.tails[0] = frame_bytes[offset++]; + frame.tails[1] = frame_bytes[offset++]; + + last_error_.clear(); + return true; + } + +private: + std::vector buffer_; + std::string last_error_; + double vref_ = 4.5; + double gain_ = 6.0; + bool bypass_checksum_ = true; +}; + +} // namespace xyparser diff --git a/XYParser/XYEegParserExample.cpp b/XYParser/XYEegParserExample.cpp new file mode 100644 index 0000000..7c5b008 --- /dev/null +++ b/XYParser/XYEegParserExample.cpp @@ -0,0 +1,112 @@ +#include "pch.h" +#include "XYParserApi.h" + +#include +#include +#include + +namespace { + +std::vector BuildMinimalFrame(std::uint8_t channel_count) +{ + constexpr std::size_t kSamplesPerFrame = 5; + constexpr std::uint8_t kHeader = 0xAA; + constexpr std::uint8_t kTail = 0x55; + constexpr std::size_t kTagLen = 25; + + const std::size_t sample_bytes = static_cast(channel_count) * 3 + 2; + const std::uint16_t payload_length = static_cast(sample_bytes * kSamplesPerFrame); + const std::size_t frame_size = 1 + kTagLen + payload_length + 2; + + std::vector frame(frame_size, 0); + std::size_t offset = 0; + + frame[offset++] = kHeader; + + // index, little endian + frame[offset++] = 0x01; + frame[offset++] = 0x00; + frame[offset++] = 0x00; + frame[offset++] = 0x00; + + // payload length, big endian + frame[offset++] = static_cast((payload_length >> 8) & 0xFF); + frame[offset++] = static_cast(payload_length & 0xFF); + + frame[offset++] = 95; // battery + frame[offset++] = channel_count; // channelCount + + // elevation / roll / yaw / ecg / spo2 / reserved[6] + offset += 2 + 2 + 2 + 2 + 2 + 6; + + // Build 5 samples. Each channel uses 3 ADC bytes, followed by trigger fields. + for (std::size_t sample = 0; sample < kSamplesPerFrame; ++sample) { + for (std::size_t channel = 0; channel < channel_count; ++channel) { + frame[offset++] = 0x00; + frame[offset++] = 0x00; + frame[offset++] = static_cast(sample + channel + 1); + } + frame[offset++] = 0x00; // triggerType + frame[offset++] = 0x00; // triggerIndex + } + + frame[offset++] = 0x00; // crc, ignored when bypass checksum is enabled + frame[offset++] = kTail; + frame[offset++] = kTail; + + return frame; +} + +} // namespace + +void MinimalExampleFor8ChParser() +{ + XYParserHandle parser = XYParser_CreateParser(8); + if (parser == nullptr) { + return; + } + XYParser_SetAdcParams(parser, 4.5, 6.0); + XYParser_SetBypassChecksum(parser, 1); + + const std::vector raw_bytes = BuildMinimalFrame(8); + std::array summaries{}; + const int frame_count = XYParser_Feed(parser, + raw_bytes.data(), + raw_bytes.size(), + summaries.data(), + static_cast(summaries.size())); + + if (frame_count > 0) { + const XYParserFrameSummary& frame = summaries.front(); + const double first_channel_uv = frame.channel_values_uv[0][0]; + (void)first_channel_uv; + } + + XYParser_DestroyParser(parser); +} + +void MinimalExampleFor64ChParser() +{ + XYParserHandle parser = XYParser_CreateParser(64); + if (parser == nullptr) { + return; + } + XYParser_SetAdcParams(parser, 4.5, 6.0); + XYParser_SetBypassChecksum(parser, 1); + + const std::vector raw_bytes = BuildMinimalFrame(64); + std::array summaries{}; + const int frame_count = XYParser_Feed(parser, + raw_bytes.data(), + raw_bytes.size(), + summaries.data(), + static_cast(summaries.size())); + + if (frame_count > 0) { + const XYParserFrameSummary& frame = summaries.front(); + const std::uint8_t battery = frame.battery; + (void)battery; + } + + XYParser_DestroyParser(parser); +} diff --git a/XYParser/XYParser.sln b/XYParser/XYParser.sln new file mode 100644 index 0000000..61f8752 --- /dev/null +++ b/XYParser/XYParser.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36429.23 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XYParser", "XYParser.vcxproj", "{CB1FF804-BB1F-41C8-92FA-7B15F6B86347}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CB1FF804-BB1F-41C8-92FA-7B15F6B86347}.Debug|x64.ActiveCfg = Debug|x64 + {CB1FF804-BB1F-41C8-92FA-7B15F6B86347}.Debug|x64.Build.0 = Debug|x64 + {CB1FF804-BB1F-41C8-92FA-7B15F6B86347}.Debug|x86.ActiveCfg = Debug|Win32 + {CB1FF804-BB1F-41C8-92FA-7B15F6B86347}.Debug|x86.Build.0 = Debug|Win32 + {CB1FF804-BB1F-41C8-92FA-7B15F6B86347}.Release|x64.ActiveCfg = Release|x64 + {CB1FF804-BB1F-41C8-92FA-7B15F6B86347}.Release|x64.Build.0 = Release|x64 + {CB1FF804-BB1F-41C8-92FA-7B15F6B86347}.Release|x86.ActiveCfg = Release|Win32 + {CB1FF804-BB1F-41C8-92FA-7B15F6B86347}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F6206831-0432-4ABB-B939-97EC2B8EAB79} + EndGlobalSection +EndGlobal diff --git a/XYParser/XYParser.vcxproj b/XYParser/XYParser.vcxproj new file mode 100644 index 0000000..36218c8 --- /dev/null +++ b/XYParser/XYParser.vcxproj @@ -0,0 +1,161 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {cb1ff804-bb1f-41c8-92fa-7b15f6b86347} + XYParser + 10.0 + + + + DynamicLibrary + true + v143 + Unicode + + + DynamicLibrary + false + v143 + true + Unicode + + + DynamicLibrary + true + v143 + Unicode + + + DynamicLibrary + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;XYPARSER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + + + + Level3 + true + true + true + WIN32;NDEBUG;XYPARSER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + + + + Level3 + true + _DEBUG;XYPARSER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + + + + Level3 + true + true + true + NDEBUG;XYPARSER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + + diff --git a/XYParser/XYParser.vcxproj.filters b/XYParser/XYParser.vcxproj.filters new file mode 100644 index 0000000..406b3bf --- /dev/null +++ b/XYParser/XYParser.vcxproj.filters @@ -0,0 +1,57 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + diff --git a/XYParser/XYParser/x64/Debug/XYEegParser64.obj b/XYParser/XYParser/x64/Debug/XYEegParser64.obj new file mode 100644 index 0000000..0ea73f8 Binary files /dev/null and b/XYParser/XYParser/x64/Debug/XYEegParser64.obj differ diff --git a/XYParser/XYParser/x64/Debug/XYEegParser8.obj b/XYParser/XYParser/x64/Debug/XYEegParser8.obj new file mode 100644 index 0000000..df42ac7 Binary files /dev/null and b/XYParser/XYParser/x64/Debug/XYEegParser8.obj differ diff --git a/XYParser/XYParser/x64/Debug/XYEegParserExample.obj b/XYParser/XYParser/x64/Debug/XYEegParserExample.obj new file mode 100644 index 0000000..6150bb4 Binary files /dev/null and b/XYParser/XYParser/x64/Debug/XYEegParserExample.obj differ diff --git a/XYParser/XYParser/x64/Debug/XYParser.dll.recipe b/XYParser/XYParser/x64/Debug/XYParser.dll.recipe new file mode 100644 index 0000000..ea139e9 --- /dev/null +++ b/XYParser/XYParser/x64/Debug/XYParser.dll.recipe @@ -0,0 +1,11 @@ + + + + + C:\Users\xyyl666\Desktop\XYParser\XYParser\x64\Debug\XYParser.dll + + + + + + \ No newline at end of file diff --git a/XYParser/XYParser/x64/Debug/XYParser.ilk b/XYParser/XYParser/x64/Debug/XYParser.ilk new file mode 100644 index 0000000..ef3b14e Binary files /dev/null and b/XYParser/XYParser/x64/Debug/XYParser.ilk differ diff --git a/XYParser/XYParser/x64/Debug/XYParser.log b/XYParser/XYParser/x64/Debug/XYParser.log new file mode 100644 index 0000000..3959187 --- /dev/null +++ b/XYParser/XYParser/x64/Debug/XYParser.log @@ -0,0 +1,9 @@ + pch.cpp + dllmain.cpp + XYParserApi.cpp + XYEegParser8.cpp + XYEegParser64.cpp + XYEegParserExample.cpp + 正在生成代码... + 正在创建库 C:\Users\xyyl666\Desktop\XYParser\XYParser\x64\Debug\XYParser.lib 和对象 C:\Users\xyyl666\Desktop\XYParser\XYParser\x64\Debug\XYParser.exp + XYParser.vcxproj -> C:\Users\xyyl666\Desktop\XYParser\XYParser\x64\Debug\XYParser.dll diff --git a/XYParser/XYParser/x64/Debug/XYParser.pch b/XYParser/XYParser/x64/Debug/XYParser.pch new file mode 100644 index 0000000..3fa7271 Binary files /dev/null and b/XYParser/XYParser/x64/Debug/XYParser.pch differ diff --git a/XYParser/XYParser/x64/Debug/XYParser.tlog/CL.command.1.tlog b/XYParser/XYParser/x64/Debug/XYParser.tlog/CL.command.1.tlog new file mode 100644 index 0000000..2a50d3f Binary files /dev/null and b/XYParser/XYParser/x64/Debug/XYParser.tlog/CL.command.1.tlog differ diff --git a/XYParser/XYParser/x64/Debug/XYParser.tlog/CL.read.1.tlog b/XYParser/XYParser/x64/Debug/XYParser.tlog/CL.read.1.tlog new file mode 100644 index 0000000..05cef0a Binary files /dev/null and b/XYParser/XYParser/x64/Debug/XYParser.tlog/CL.read.1.tlog differ diff --git a/XYParser/XYParser/x64/Debug/XYParser.tlog/CL.write.1.tlog b/XYParser/XYParser/x64/Debug/XYParser.tlog/CL.write.1.tlog new file mode 100644 index 0000000..1fa28e7 Binary files /dev/null and b/XYParser/XYParser/x64/Debug/XYParser.tlog/CL.write.1.tlog differ diff --git a/XYParser/XYParser/x64/Debug/XYParser.tlog/Cl.items.tlog b/XYParser/XYParser/x64/Debug/XYParser.tlog/Cl.items.tlog new file mode 100644 index 0000000..31eae9c --- /dev/null +++ b/XYParser/XYParser/x64/Debug/XYParser.tlog/Cl.items.tlog @@ -0,0 +1,6 @@ +C:\Users\xyyl666\Desktop\XYParser\XYParser\dllmain.cpp;C:\Users\xyyl666\Desktop\XYParser\XYParser\XYParser\x64\Debug\dllmain.obj +C:\Users\xyyl666\Desktop\XYParser\XYParser\pch.cpp;C:\Users\xyyl666\Desktop\XYParser\XYParser\XYParser\x64\Debug\pch.obj +C:\Users\xyyl666\Desktop\XYParser\XYParser\XYParserApi.cpp;C:\Users\xyyl666\Desktop\XYParser\XYParser\XYParser\x64\Debug\XYParserApi.obj +C:\Users\xyyl666\Desktop\XYParser\XYParser\XYEegParser8.cpp;C:\Users\xyyl666\Desktop\XYParser\XYParser\XYParser\x64\Debug\XYEegParser8.obj +C:\Users\xyyl666\Desktop\XYParser\XYParser\XYEegParser64.cpp;C:\Users\xyyl666\Desktop\XYParser\XYParser\XYParser\x64\Debug\XYEegParser64.obj +C:\Users\xyyl666\Desktop\XYParser\XYParser\XYEegParserExample.cpp;C:\Users\xyyl666\Desktop\XYParser\XYParser\XYParser\x64\Debug\XYEegParserExample.obj diff --git a/XYParser/XYParser/x64/Debug/XYParser.tlog/XYParser.lastbuildstate b/XYParser/XYParser/x64/Debug/XYParser.tlog/XYParser.lastbuildstate new file mode 100644 index 0000000..55e2ec0 --- /dev/null +++ b/XYParser/XYParser/x64/Debug/XYParser.tlog/XYParser.lastbuildstate @@ -0,0 +1,2 @@ +PlatformToolSet=v143:VCToolArchitecture=Native32Bit:VCToolsVersion=14.44.35207:TargetPlatformVersion=10.0.26100.0: +Debug|x64|C:\Users\xyyl666\Desktop\XYParser\XYParser\| diff --git a/XYParser/XYParser/x64/Debug/XYParser.tlog/link.command.1.tlog b/XYParser/XYParser/x64/Debug/XYParser.tlog/link.command.1.tlog new file mode 100644 index 0000000..31a2e57 Binary files /dev/null and b/XYParser/XYParser/x64/Debug/XYParser.tlog/link.command.1.tlog differ diff --git a/XYParser/XYParser/x64/Debug/XYParser.tlog/link.read.1.tlog b/XYParser/XYParser/x64/Debug/XYParser.tlog/link.read.1.tlog new file mode 100644 index 0000000..7234974 Binary files /dev/null and b/XYParser/XYParser/x64/Debug/XYParser.tlog/link.read.1.tlog differ diff --git a/XYParser/XYParser/x64/Debug/XYParser.tlog/link.secondary.1.tlog b/XYParser/XYParser/x64/Debug/XYParser.tlog/link.secondary.1.tlog new file mode 100644 index 0000000..5d99fb7 --- /dev/null +++ b/XYParser/XYParser/x64/Debug/XYParser.tlog/link.secondary.1.tlog @@ -0,0 +1,4 @@ +^C:\USERS\XYYL666\DESKTOP\XYPARSER\XYPARSER\XYPARSER\X64\DEBUG\DLLMAIN.OBJ|C:\USERS\XYYL666\DESKTOP\XYPARSER\XYPARSER\XYPARSER\X64\DEBUG\PCH.OBJ|C:\USERS\XYYL666\DESKTOP\XYPARSER\XYPARSER\XYPARSER\X64\DEBUG\XYEEGPARSER64.OBJ|C:\USERS\XYYL666\DESKTOP\XYPARSER\XYPARSER\XYPARSER\X64\DEBUG\XYEEGPARSER8.OBJ|C:\USERS\XYYL666\DESKTOP\XYPARSER\XYPARSER\XYPARSER\X64\DEBUG\XYEEGPARSEREXAMPLE.OBJ|C:\USERS\XYYL666\DESKTOP\XYPARSER\XYPARSER\XYPARSER\X64\DEBUG\XYPARSERAPI.OBJ +C:\Users\xyyl666\Desktop\XYParser\XYParser\x64\Debug\XYParser.lib +C:\Users\xyyl666\Desktop\XYParser\XYParser\x64\Debug\XYParser.EXP +C:\Users\xyyl666\Desktop\XYParser\XYParser\XYParser\x64\Debug\XYParser.ilk diff --git a/XYParser/XYParser/x64/Debug/XYParser.tlog/link.write.1.tlog b/XYParser/XYParser/x64/Debug/XYParser.tlog/link.write.1.tlog new file mode 100644 index 0000000..aed7cd5 Binary files /dev/null and b/XYParser/XYParser/x64/Debug/XYParser.tlog/link.write.1.tlog differ diff --git a/XYParser/XYParser/x64/Debug/XYParserApi.obj b/XYParser/XYParser/x64/Debug/XYParserApi.obj new file mode 100644 index 0000000..ab5ac90 Binary files /dev/null and b/XYParser/XYParser/x64/Debug/XYParserApi.obj differ diff --git a/XYParser/XYParser/x64/Debug/dllmain.obj b/XYParser/XYParser/x64/Debug/dllmain.obj new file mode 100644 index 0000000..351aa37 Binary files /dev/null and b/XYParser/XYParser/x64/Debug/dllmain.obj differ diff --git a/XYParser/XYParser/x64/Debug/pch.obj b/XYParser/XYParser/x64/Debug/pch.obj new file mode 100644 index 0000000..05f55b9 Binary files /dev/null and b/XYParser/XYParser/x64/Debug/pch.obj differ diff --git a/XYParser/XYParser/x64/Debug/vc143.idb b/XYParser/XYParser/x64/Debug/vc143.idb new file mode 100644 index 0000000..06d04d9 Binary files /dev/null and b/XYParser/XYParser/x64/Debug/vc143.idb differ diff --git a/XYParser/XYParser/x64/Debug/vc143.pdb b/XYParser/XYParser/x64/Debug/vc143.pdb new file mode 100644 index 0000000..6ad8431 Binary files /dev/null and b/XYParser/XYParser/x64/Debug/vc143.pdb differ diff --git a/XYParser/XYParserApi.cpp b/XYParser/XYParserApi.cpp new file mode 100644 index 0000000..4b4c35e --- /dev/null +++ b/XYParser/XYParserApi.cpp @@ -0,0 +1,154 @@ +#include "pch.h" +#include "XYParserApi.h" + +#include "XYEegParser8.h" +#include "XYEegParser64.h" + +#include +#include +#include +#include + +namespace { + +struct ParserContext { + std::uint8_t channel_count = 0; + XYEegParser8 parser8; + XYEegParser64 parser64; + std::string last_error; +}; + +void FillSummary(const XYEegFrame8& frame, XYParserFrameSummary& summary) +{ + summary.frame_index = frame.index; + summary.channel_count = frame.channel_count; + summary.battery = frame.battery; + summary.sample_count = static_cast(frame.samples.size()); + for (std::size_t sample_index = 0; sample_index < XYPARSER_SAMPLES_PER_FRAME; ++sample_index) { + summary.trigger_types[sample_index] = frame.samples[sample_index].trigger_type; + summary.trigger_indices[sample_index] = frame.samples[sample_index].trigger_index; + for (std::size_t channel_index = 0; channel_index < XYPARSER_MAX_CHANNELS; ++channel_index) { + summary.channel_values_uv[sample_index][channel_index] = + channel_index < frame.channel_count + ? frame.samples[sample_index].channel_values_uv[channel_index] + : 0.0; + } + } +} + +void FillSummary(const XYEegFrame64& frame, XYParserFrameSummary& summary) +{ + summary.frame_index = frame.index; + summary.channel_count = frame.channel_count; + summary.battery = frame.battery; + summary.sample_count = static_cast(frame.samples.size()); + for (std::size_t sample_index = 0; sample_index < XYPARSER_SAMPLES_PER_FRAME; ++sample_index) { + summary.trigger_types[sample_index] = frame.samples[sample_index].trigger_type; + summary.trigger_indices[sample_index] = frame.samples[sample_index].trigger_index; + for (std::size_t channel_index = 0; channel_index < XYPARSER_MAX_CHANNELS; ++channel_index) { + summary.channel_values_uv[sample_index][channel_index] = + channel_index < frame.channel_count + ? frame.samples[sample_index].channel_values_uv[channel_index] + : 0.0; + } + } +} + +} // namespace + +extern "C" { + +XYParserHandle XYParser_CreateParser(std::uint8_t channel_count) +{ + if (channel_count != 8 && channel_count != 64) { + return nullptr; + } + + ParserContext* context = new (std::nothrow) ParserContext(); + if (context == nullptr) { + return nullptr; + } + + context->channel_count = channel_count; + return context; +} + +void XYParser_DestroyParser(XYParserHandle handle) +{ + ParserContext* context = static_cast(handle); + delete context; +} + +void XYParser_SetAdcParams(XYParserHandle handle, double vref, double gain) +{ + ParserContext* context = static_cast(handle); + if (context == nullptr) { + return; + } + + if (context->channel_count == 8) { + context->parser8.SetAdcParams(vref, gain); + } else { + context->parser64.SetAdcParams(vref, gain); + } +} + +void XYParser_SetBypassChecksum(XYParserHandle handle, int bypass) +{ + ParserContext* context = static_cast(handle); + if (context == nullptr) { + return; + } + + const bool enabled = bypass != 0; + if (context->channel_count == 8) { + context->parser8.SetBypassChecksum(enabled); + } else { + context->parser64.SetBypassChecksum(enabled); + } +} + +int XYParser_Feed(XYParserHandle handle, + const std::uint8_t* data, + std::size_t size, + XYParserFrameSummary* out_summaries, + int max_summaries) +{ + ParserContext* context = static_cast(handle); + if (context == nullptr || data == nullptr || size == 0) { + return 0; + } + + if (max_summaries < 0) { + max_summaries = 0; + } + + if (context->channel_count == 8) { + const std::vector frames = context->parser8.Feed(data, size); + context->last_error = context->parser8.LastError(); + const int write_count = std::min(static_cast(frames.size()), max_summaries); + for (int i = 0; i < write_count; ++i) { + FillSummary(frames[static_cast(i)], out_summaries[i]); + } + return write_count; + } + + const std::vector frames = context->parser64.Feed(data, size); + context->last_error = context->parser64.LastError(); + const int write_count = std::min(static_cast(frames.size()), max_summaries); + for (int i = 0; i < write_count; ++i) { + FillSummary(frames[static_cast(i)], out_summaries[i]); + } + return write_count; +} + +const char* XYParser_GetLastError(XYParserHandle handle) +{ + ParserContext* context = static_cast(handle); + if (context == nullptr) { + return "invalid parser handle"; + } + return context->last_error.c_str(); +} + +} diff --git a/XYParser/XYParserApi.h b/XYParser/XYParserApi.h new file mode 100644 index 0000000..972897c --- /dev/null +++ b/XYParser/XYParserApi.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include + +#ifdef XYPARSER_EXPORTS +#define XYPARSER_API __declspec(dllexport) +#else +#define XYPARSER_API __declspec(dllimport) +#endif + +extern "C" { + +typedef void* XYParserHandle; + +enum { + XYPARSER_MAX_CHANNELS = 64, + XYPARSER_SAMPLES_PER_FRAME = 5 +}; + +struct XYParserFrameSummary { + std::uint32_t frame_index; + std::uint8_t channel_count; + std::uint8_t battery; + std::uint8_t sample_count; + double channel_values_uv[XYPARSER_SAMPLES_PER_FRAME][XYPARSER_MAX_CHANNELS]; + std::uint8_t trigger_types[XYPARSER_SAMPLES_PER_FRAME]; + std::uint8_t trigger_indices[XYPARSER_SAMPLES_PER_FRAME]; +}; + +XYPARSER_API XYParserHandle XYParser_CreateParser(std::uint8_t channel_count); +XYPARSER_API void XYParser_DestroyParser(XYParserHandle handle); +XYPARSER_API void XYParser_SetAdcParams(XYParserHandle handle, double vref, double gain); +XYPARSER_API void XYParser_SetBypassChecksum(XYParserHandle handle, int bypass); +XYPARSER_API int XYParser_Feed(XYParserHandle handle, + const std::uint8_t* data, + std::size_t size, + XYParserFrameSummary* out_summaries, + int max_summaries); +XYPARSER_API const char* XYParser_GetLastError(XYParserHandle handle); + +} diff --git a/XYParser/dllmain.cpp b/XYParser/dllmain.cpp new file mode 100644 index 0000000..daed8c8 --- /dev/null +++ b/XYParser/dllmain.cpp @@ -0,0 +1,19 @@ +// dllmain.cpp : 定义 DLL 应用程序的入口点。 +#include "pch.h" + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + diff --git a/XYParser/framework.h b/XYParser/framework.h new file mode 100644 index 0000000..80cbbc9 --- /dev/null +++ b/XYParser/framework.h @@ -0,0 +1,5 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容 +// Windows 头文件 +#include diff --git a/XYParser/pch.cpp b/XYParser/pch.cpp new file mode 100644 index 0000000..b6fb8f4 --- /dev/null +++ b/XYParser/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: 与预编译标头对应的源文件 + +#include "pch.h" + +// 当使用预编译的头时,需要使用此源文件,编译才能成功。 diff --git a/XYParser/pch.h b/XYParser/pch.h new file mode 100644 index 0000000..9660927 --- /dev/null +++ b/XYParser/pch.h @@ -0,0 +1,13 @@ +// pch.h: 这是预编译标头文件。 +// 下方列出的文件仅编译一次,提高了将来生成的生成性能。 +// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。 +// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。 +// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。 + +#ifndef PCH_H +#define PCH_H + +// 添加要在此处预编译的标头 +#include "framework.h" + +#endif //PCH_H diff --git a/XYParser/x64/Debug/XYParser.dll b/XYParser/x64/Debug/XYParser.dll new file mode 100644 index 0000000..37fb628 Binary files /dev/null and b/XYParser/x64/Debug/XYParser.dll differ diff --git a/XYParser/x64/Debug/XYParser.exp b/XYParser/x64/Debug/XYParser.exp new file mode 100644 index 0000000..5bad8ce Binary files /dev/null and b/XYParser/x64/Debug/XYParser.exp differ diff --git a/XYParser/x64/Debug/XYParser.lib b/XYParser/x64/Debug/XYParser.lib new file mode 100644 index 0000000..8d4c2ad Binary files /dev/null and b/XYParser/x64/Debug/XYParser.lib differ diff --git a/XYParser/x64/Debug/XYParser.pdb b/XYParser/x64/Debug/XYParser.pdb new file mode 100644 index 0000000..f538c6a Binary files /dev/null and b/XYParser/x64/Debug/XYParser.pdb differ