public string SendRecv(string action, string actionType, string data) { IntPtr dataPointer = default(IntPtr); IntPtr dataTypePointer = default(IntPtr); IntPtr sizePointer = default(IntPtr); IntPtr pointerToDataPointer = default(IntPtr); IntPtr tempResultPointer = default(IntPtr); IntPtr countPointer = default(IntPtr); IntPtr resultPointer = default(IntPtr); string xml = string.Empty; try { BidiRequest bidiRequest = (BidiRequest)Activator.CreateInstance(typeof(BidiRequest), true); IBidiRequest iBidiRequest = (IBidiRequest)bidiRequest; iBidiRequest.SetSchema(action); // Set the input data for the request, if any if (data.Length != 0) { dataPointer = Marshal.AllocCoTaskMem(data.Length * sizeof(char)); var chars = data.ToCharArray(); Marshal.Copy(chars, 0, dataPointer, data.Length); iBidiRequest.SetInputData((UInt32)BIDI_TYPE.BIDI_BLOB, dataPointer, (UInt32)data.Length * sizeof(char)); } // Send request to driver var val = _iBidiSpl.SendRecv(actionType, iBidiRequest); // Check if request was a success resultPointer = Marshal.AllocCoTaskMem(sizeof(Int32)); // Call the method iBidiRequest.GetResult(resultPointer); // Get the value Int32 result = (Int32)Marshal.PtrToStructure(resultPointer, typeof(Int32)); const int resultSuccess = 0; if (result == resultSuccess) { // Check if any data was returned. Note: dxp01sdk.strings.ENDJOB // and dxp01sdk.strings.PRINTER_ACTION do not return any values. // First allocate memory countPointer = Marshal.AllocCoTaskMem(sizeof(Int32)); // Call the method iBidiRequest.GetEnumCount(countPointer); // Get the value Int32 count = (Int32)Marshal.PtrToStructure(countPointer, typeof(Int32)); if (count != 0) { // Driver sent some data. Now retrieve the data sent by the driver // First allocate memory for type and size dataTypePointer = Marshal.AllocCoTaskMem(sizeof(Int32)); sizePointer = Marshal.AllocCoTaskMem(sizeof(Int32)); // Now allocate memory for data. Also add level of indirection. IntPtr ptrTemp = default(IntPtr); pointerToDataPointer = Marshal.AllocCoTaskMem(sizeof(Int32)); Marshal.StructureToPtr(ptrTemp, pointerToDataPointer, false); // Finally, retrieve the data sent by the driver string schema = string.Empty; iBidiRequest.GetOutputData(0, schema, dataTypePointer, pointerToDataPointer, sizePointer); // Get the size of the data in bytes returned from SendRecv method. Int32 size = (Int32)Marshal.PtrToStructure(sizePointer, typeof(Int32)); // Get the data itself. First remove level of indirection tempResultPointer = Marshal.ReadIntPtr(pointerToDataPointer); // Get Unicode string from pointer. Unicode characters are 16-bit characters. // size contains the number of bytes returned by SendRecv method xml = Marshal.PtrToStringUni(tempResultPointer, size / sizeof(char)); } } } finally { Marshal.FreeCoTaskMem(dataPointer); Marshal.FreeCoTaskMem(sizePointer); Marshal.FreeCoTaskMem(dataTypePointer); Marshal.FreeCoTaskMem(pointerToDataPointer); Marshal.FreeCoTaskMem(tempResultPointer); Marshal.FreeCoTaskMem(countPointer); Marshal.FreeCoTaskMem(resultPointer); } return(xml); }
private IEnumerable <Tuple <string, object> > GetData(IBidiRequest bidiRequest) { bidiRequest.GetEnumCount(out uint count); for (uint i = 0; i < count; i++) { bidiRequest.GetOutputData(i, out var schemaPtr, out var type, out var dataPtr, out var size); try { var sc = Marshal.PtrToStringUni(schemaPtr) ?? throw new NullReferenceException("sc"); switch ((BIDI_DATA_TYPE)type) { case BIDI_DATA_TYPE.BIDI_NULL: yield return(new Tuple <string, object>(sc, null)); break; case BIDI_DATA_TYPE.BIDI_INT: yield return(new Tuple <string, object>(sc, (UInt32)Marshal.PtrToStructure(dataPtr, typeof(UInt32)))); break; case BIDI_DATA_TYPE.BIDI_FLOAT: yield return(new Tuple <string, object>(sc, (float)Marshal.PtrToStructure(dataPtr, typeof(float)))); break; case BIDI_DATA_TYPE.BIDI_BOOL: yield return(new Tuple <string, object>(sc, (bool)Marshal.PtrToStructure(dataPtr, typeof(bool)))); break; case BIDI_DATA_TYPE.BIDI_STRING: yield return(new Tuple <string, object>(sc, Marshal.PtrToStringUni(dataPtr))); break; case BIDI_DATA_TYPE.BIDI_TEXT: yield return(new Tuple <string, object>(sc, Marshal.PtrToStringUni(dataPtr))); break; case BIDI_DATA_TYPE.BIDI_ENUM: yield return(new Tuple <string, object>(sc, Marshal.PtrToStringUni(dataPtr))); break; case BIDI_DATA_TYPE.BIDI_BLOB: var bytes = new byte[size]; Marshal.Copy(dataPtr, bytes, 0, (int)size); yield return(new Tuple <string, object>(sc, bytes)); break; default: throw new ArgumentOutOfRangeException(nameof(type)); } } finally { Marshal.FreeCoTaskMem(schemaPtr); Marshal.FreeCoTaskMem(dataPtr); } } }