C# Basic Stamp Tokenizer Class
Toft
Posts: 4
Here's what I've got so far;
But I'm having trouble making calls to the TestAlign functions and Compile Functions. I think I'm not marshalling properly?
I try:
And it just fails. Anyone have ideas?
SharpStamp.cs
But I'm having trouble making calls to the TestAlign functions and Compile Functions. I think I'm not marshalling properly?
I try:
IntPtr RecPtr = IntPtr.Zero; IntPtr TokPtr = IntPtr.Zero; Stamp.TModuleRec myRec = new Stamp.TModuleRec(); RecPtr = Marshal.AllocCoTaskMem(4); Marshal.StructureToPtr(myRec, RecPtr, true); Stamp.tokenizer_test_align(ref RecPtr);
And it just fails. Anyone have ideas?
SharpStamp.cs
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace CSStampServer { class Stamp { /// <summary> /// The value returned is in the format: XYY ;where X is the major version number and Y is the minor. /// For example, if the Version function returned 116, that indicates the version of the tokenizer is 1.16. /// If Version returned 123, that would indicate the tokenizer is version 1.23. /// </summary> /// <returns></returns> [noparse][[/noparse]DllImport("tokenizer.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall, EntryPoint = "Version")] public static extern int tokenizer_version(); /// <summary> /// Tests the alignment and sets values to, 0, 1, 2, 3, ... 32. /// </summary> /// <param name="Rec"></param> /// <returns></returns> [noparse][[/noparse]DllImport("tokenizer.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall, EntryPoint = "TestRecAlignment")] public static extern bool tokenizer_test_align(ref IntPtr /* TModuleRec* */ Rec); /// <summary> /// /// The Compile function for the basic stamp tokenizer. /// </summary> /// <param name="Rec">A pointer to an existing TModuleRec structure.</param> /// <param name="Src">A pointer to an existing Source buffer.</param> /// <param name="DirectivesOnly">A Boolean value that provides an option of only tokenizing the “compiler directives” from the source code, rather than the entire source. /// This option is helpful when the calling program needs to determine only the target module, serial port or project files that may be specified by the PBASIC source code. /// TRUE : Causes the tokenizer to only parse the directives from the source code. /// FALSE : (Normal mode) Causes the tokenizer to parse the entire source code, including all directives (depending on the ParseStampDirective parameter).</param> /// <param name="ParseStampDirective">A Boolean value that provides an option of parsing the Stamp directive from the source code, rather than accepting a value in the TargetModule field of the TModuleRec structure. /// TRUE : (Normal mode) Causes the tokenizer to parse the Stamp directive, if present, from the source code. /// If a valid directive is found, the compiler stores the value of the target module in the TargetModule field and compiles. If no Stamp directive is found, the tokenizer generates an error. /// FALSE : Causes the tokenizer to ignore any Stamp directives in the source and instead use the value currently in the TargetModule field to compile the code. /// This means, the TargetModule field MUST be set to the proper value BEFORE calling Compile.</param> /// <param name="Ref">An optional pointer to an existing TSrcTokReference buffer. Set to NULL when not used.</param> /// <returns></returns> [noparse][[/noparse]DllImport("tokenizer.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall, EntryPoint = "Compile")] public static extern bool tokenizer_compile(IntPtr /* TModuleRec* */ Rec, [noparse][[/noparse]MarshalAs(UnmanagedType.LPStr)]IntPtr /* char* */ Src, [noparse][[/noparse]MarshalAs(UnmanagedType.Bool)]bool DirectivesOnly, [noparse][[/noparse]MarshalAs(UnmanagedType.Bool)]bool ParseStampDirective, IntPtr /* TSrcTokReference* */ Ref); #region Unmanaged Structs Implementation [noparse][[/noparse]StructLayout(LayoutKind.Sequential)] internal struct STAMP_IF { public IntPtr /* TSrcTokReference* */ SrcTokenReference; public string Name; public string Decription; public IntPtr /* TModuleRec* */ TokenModule; } /// <summary> /// This structure is optional since it is intended for use by PBASIC simulators. /// </summary> [noparse][[/noparse]StructLayout(LayoutKind.Sequential)] internal struct TSrkTokReference { [noparse][[/noparse]MarshalAs(UnmanagedType.U2)] public ushort SrcStart; [noparse][[/noparse]MarshalAs(UnmanagedType.U2)] public ushort TokStart; } /// <summary> /// This is the structure that is used for the Basic Stamp Tokenization process. (The information sent to the Compiler.) /// </summary> [noparse][[/noparse]StructLayout(LayoutKind.Sequential)] internal class TModuleRec { public bool Succeeded; public string Error; public bool DebugFlag; public byte TargetModule; public int TargetStart; [noparse][[/noparse]MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] public IntPtr[noparse][[/noparse]] /* char** */ ProjectFiles; [noparse][[/noparse]MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] public IntPtr[noparse][[/noparse]] /* int* */ ProjectFilesStart; public string Port; public int PortStart; public int LanguageVersion; public int LanguageStart; public int SourceSize; public int ErrorStart; public int ErrorLength; [noparse][[/noparse]MarshalAs(UnmanagedType.ByValArray, SizeConst = 2048)] public byte[noparse][[/noparse]] EEPROM; [noparse][[/noparse]MarshalAs(UnmanagedType.ByValArray, SizeConst = 2048)] public byte[noparse][[/noparse]] EEPROMFlags; [noparse][[/noparse]MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[noparse][[/noparse]] VarCounts; public byte PacketCount; [noparse][[/noparse]MarshalAs(UnmanagedType.ByValArray, SizeConst = 2304)] public byte[noparse][[/noparse]] PacketBuffer; } #endregion public static string Version { get { try { return tokenizer_version().ToString(); } catch { return "Parallax Tokenizer version can't be identified or the tokenizer.dll is not installed."; } } } } }
Comments
TModuleRec and it thus gets missaligned. Fill your TModuleRec structure with characteristic values and check the memory layout with the
debugger or a hexdump.
Hope it helps.
Adrian
Here's my example:
For -calling- the rec align function, the actual struct (and all of the background stuff), is declared as follows;
I'll try to get this actually wrapped into an entire library with collections so that if other people want to use the tokenizer in C# they can!