gpt4 book ai didi

c# - 如何在 C# 中模拟 C 函数 sprintf_s 的效果?

转载 作者:太空宇宙 更新时间:2023-11-04 03:10:44 25 4
gpt4 key购买 nike

我正在尝试将我的前任用 C 编写的一些旧代码迁移到 C#。我曾尝试使用 P/invoke 方式,但遇到了 sprint_s 问题。关于如何解决这个问题或使用 C# 的 SerialPort 类编写它有什么建议吗?

    [StructLayout(LayoutKind.Sequential)]
internal struct Dcb
{
internal uint DCBLength;
internal uint BaudRate;
private BitVector32 Flags;

private ushort wReserved; // not currently used
internal ushort XonLim; // transmit XON threshold
internal ushort XoffLim; // transmit XOFF threshold

internal byte ByteSize;
internal Parity Parity;
internal StopBits StopBits;

internal sbyte XonChar; // Tx and Rx XON character
internal sbyte XoffChar; // Tx and Rx XOFF character
internal sbyte ErrorChar; // error replacement character
internal sbyte EofChar; // end of input character
internal sbyte EvtChar; // received event character
private ushort wReserved1; // reserved; do not use

private static readonly int fBinary;
private static readonly int fParity;
private static readonly int fOutxCtsFlow;
private static readonly int fOutxDsrFlow;
private static readonly BitVector32.Section fDtrControl;
private static readonly int fDsrSensitivity;
private static readonly int fTXContinueOnXoff;
private static readonly int fOutX;
private static readonly int fInX;
private static readonly int fErrorChar;
private static readonly int fNull;
private static readonly BitVector32.Section fRtsControl;
private static readonly int fAbortOnError;

static Dcb()
{
// Create Boolean Mask
int previousMask;
fBinary = BitVector32.CreateMask();
fParity = BitVector32.CreateMask(fBinary);
fOutxCtsFlow = BitVector32.CreateMask(fParity);
fOutxDsrFlow = BitVector32.CreateMask(fOutxCtsFlow);
previousMask = BitVector32.CreateMask(fOutxDsrFlow);
previousMask = BitVector32.CreateMask(previousMask);
fDsrSensitivity = BitVector32.CreateMask(previousMask);
fTXContinueOnXoff = BitVector32.CreateMask(fDsrSensitivity);
fOutX = BitVector32.CreateMask(fTXContinueOnXoff);
fInX = BitVector32.CreateMask(fOutX);
fErrorChar = BitVector32.CreateMask(fInX);
fNull = BitVector32.CreateMask(fErrorChar);
previousMask = BitVector32.CreateMask(fNull);
previousMask = BitVector32.CreateMask(previousMask);
fAbortOnError = BitVector32.CreateMask(previousMask);

// Create section Mask
BitVector32.Section previousSection;
previousSection = BitVector32.CreateSection(1);
previousSection = BitVector32.CreateSection(1, previousSection);
previousSection = BitVector32.CreateSection(1, previousSection);
previousSection = BitVector32.CreateSection(1, previousSection);
fDtrControl = BitVector32.CreateSection(2, previousSection);
previousSection = BitVector32.CreateSection(1, fDtrControl);
previousSection = BitVector32.CreateSection(1, previousSection);
previousSection = BitVector32.CreateSection(1, previousSection);
previousSection = BitVector32.CreateSection(1, previousSection);
previousSection = BitVector32.CreateSection(1, previousSection);
previousSection = BitVector32.CreateSection(1, previousSection);
fRtsControl = BitVector32.CreateSection(3, previousSection);
previousSection = BitVector32.CreateSection(1, fRtsControl);
}

public bool Binary
{
get { return Flags[fBinary]; }
set { Flags[fBinary] = value; }
}

public bool CheckParity
{
get { return Flags[fParity]; }
set { Flags[fParity] = value; }
}

public bool OutxCtsFlow
{
get { return Flags[fOutxCtsFlow]; }
set { Flags[fOutxCtsFlow] = value; }
}

public bool OutxDsrFlow
{
get { return Flags[fOutxDsrFlow]; }
set { Flags[fOutxDsrFlow] = value; }
}

public DtrControl DtrControl
{
get { return (DtrControl)Flags[fDtrControl]; }
set { Flags[fDtrControl] = (int)value; }
}

public bool DsrSensitivity
{
get { return Flags[fDsrSensitivity]; }
set { Flags[fDsrSensitivity] = value; }
}

public bool TxContinueOnXoff
{
get { return Flags[fTXContinueOnXoff]; }
set { Flags[fTXContinueOnXoff] = value; }
}

public bool OutX
{
get { return Flags[fOutX]; }
set { Flags[fOutX] = value; }
}

public bool InX
{
get { return Flags[fInX]; }
set { Flags[fInX] = value; }
}

public bool ReplaceErrorChar
{
get { return Flags[fErrorChar]; }
set { Flags[fErrorChar] = value; }
}

public bool Null
{
get { return Flags[fNull]; }
set { Flags[fNull] = value; }
}

public RtsControl RtsControl
{
get { return (RtsControl)Flags[fRtsControl]; }
set { Flags[fRtsControl] = (int)value; }
}

public bool AbortOnError
{
get { return Flags[fAbortOnError]; }
set { Flags[fAbortOnError] = value; }
}
}

public enum DtrControl : int
{
/// <summary>
/// Disables the DTR line when the device is opened and leaves it disabled.
/// </summary>
Disable = 0,

/// <summary>
/// Enables the DTR line when the device is opened and leaves it on.
/// </summary>
Enable = 1,

/// <summary>
/// Enables DTR handshaking. If handshaking is enabled, it is an error for the application to adjust the line by
/// using the EscapeCommFunction function.
/// </summary>
Handshake = 2
}
public enum RtsControl : int
{
/// <summary>
/// Disables the RTS line when the device is opened and leaves it disabled.
/// </summary>
Disable = 0,

/// <summary>
/// Enables the RTS line when the device is opened and leaves it on.
/// </summary>
Enable = 1,

/// <summary>
/// Enables RTS handshaking. The driver raises the RTS line when the "type-ahead" (input) buffer
/// is less than one-half full and lowers the RTS line when the buffer is more than
/// three-quarters full. If handshaking is enabled, it is an error for the application to
/// adjust the line by using the EscapeCommFunction function.
/// </summary>
Handshake = 2,

/// <summary>
/// Specifies that the RTS line will be high if bytes are available for transmission. After
/// all buffered bytes have been sent, the RTS line will be low.
/// </summary>
Toggle = 3
}
public enum Parity : byte
{
None = 0,
Odd = 1,
Even = 2,
Mark = 3,
Space = 4,
}
public enum StopBits : byte
{
One = 0,
OnePointFive = 1,
Two = 2
}

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool ReadFile(IntPtr handle,
byte[] buffer, uint toRead, ref uint read, IntPtr lpOverLapped);

[DllImport("msvcrt.dll", EntryPoint = "memset", CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
public static extern IntPtr MemSet(IntPtr dest, int c, int byteCount);


[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetCommTimeouts(IntPtr hFile, [In] ref COMMTIMEOUTS
lpCommTimeouts);
struct COMMTIMEOUTS
{
public UInt32 ReadIntervalTimeout;
public UInt32 ReadTotalTimeoutMultiplier;
public UInt32 ReadTotalTimeoutConstant;
public UInt32 WriteTotalTimeoutMultiplier;
public UInt32 WriteTotalTimeoutConstant;
}

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateFile(
[MarshalAs(UnmanagedType.LPTStr)] string filename,
[MarshalAs(UnmanagedType.U4)] FileAccess access,
[MarshalAs(UnmanagedType.U4)] FileShare share,
IntPtr securityAttributes, // optional SECURITY_ATTRIBUTES struct or IntPtr.Zero
[MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
[MarshalAs(UnmanagedType.U4)] FileAttributes flagsAndAttributes,
IntPtr templateFile);

struct FILE
{
IntPtr _ptr;
int _cnt;
IntPtr _base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
IntPtr _tmpfname;
};


[DllImport("kernel32.dll")]
static extern bool WriteFile(IntPtr hFile, byte[] lpBuffer,
uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten,
IntPtr lpOverLapped);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool FlushFileBuffers(IntPtr handle);

public bool InitSerialComms()
{
FILE file = new FILE();
COMMTIMEOUTS timeouts;
Dcb dcb = new Dcb();
long len;
char[] name = new char[10];
char[] settings = new char[40];
string str;

// Form the initialization file name

sprintf_s(str, 800, "%s\\SerialComms.ini", path);

// Open the initialization file
fopen_s(&file, str, "r");

// Check for errors
if (file)
{
Console.WriteLine("Error: cannot open file %s\n");
return false;
}

// Scan the serial port name
fgets(name, 10, file);
len = strlen(name);
name[len - 1] = 0;

// Scan the serial port settings
fgets(settings, 40, file);
len = settings.Length;
settings[len - 1] = 0;

// Scan the timeout settings
fgets(str, 40, file); len = strlen(str); string[len - 1] = 0;
sscanf_s(str, "%d,%d,%d,%d,%d",
&timeouts.ReadIntervalTimeout,
&timeouts.ReadTotalTimeoutConstant,
&timeouts.ReadTotalTimeoutMultiplier,
&timeouts.WriteTotalTimeoutConstant,
&timeouts.WriteTotalTimeoutMultiplier);

// Close the initialization file
fclose(file);

// Open the serial port
port = CreateFile(name, GENERIC_READ | GENERIC_WRITE,
0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);

// Check for errors
if (port == INVALID_HANDLE_VALUE)
{
// Report the error and return
fprintf(stderr, "Error: cannot open serial port %s\n", name);
fflush(stderr);
return false;
}

// Build the serial port device control block
MemSet(dcb., 0, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
if (!BuildCommDCB(settings, &dcb))
{
// Report the error and return
fprintf(stderr, "Error: cannot create device control block for %s\n", name);
CloseHandle(port);
fflush(stderr);
return false;
}

// Configure the serial port
if (!SetCommState(port, &dcb))
{
// Report the error and return
fprintf(stderr, "Error: cannot configure serial port %s\n", name);
CloseHandle(port);
fflush(stderr);
return false;
}

// Set the timeouts for the serial port
if (!SetCommTimeouts(port, &timeouts))
{
// Report the error and return
fprintf(stderr, "Error: cannot set timeouts for %s\n", name);
CloseHandle(port);
fflush(stderr);
return false;
}

// Success
return true;
}

bool ReceiveReply(IntPtr port, ref byte[] reply, ref byte num)
{

uint num_read = 0;
uint num_to_read = 255;
ushort crc = 0XFFFF;
byte i, j;

// Clear the reply buffer
//reply = new byte[255];

num = 0;

// Read the data
if (!ReadFile(port, reply, num_to_read, ref num_read, IntPtr.Zero)) return false;

// Check number of bytes that were read
if (num_read < 2) return false;

// Check number of bytes that were read
if (num_read > 255) return false;

// Form the CRC
for (i = 0; i < num_read - 2; i++)
{
crc ^= reply[i];
for (j = 0; j < 8; j++)
{
ushort flag = (ushort) (crc & 0X0001);
crc >>= 1;
//TODO: risky flag check
if (flag == 0) crc ^= 0XA001;
}
}

// Check the CRC
if (reply[i++] != (crc & 0X00FF)) return false;
if (reply[i++] != (crc & 0XFF00) >> 8) return false;
num = (byte)(num_read - 2);

// Success
return true;
}


public static bool SendRequest(IntPtr port, ref byte[] request, ref byte num)
{
ushort crc = 0XFFFF;
byte i, j;

// Check number of bytes
if (num > 253) return false;

// Set number of bytes to write
uint num_to_write = num;

// Form the CRC
for (i = 0; i < num_to_write; i++)
{
crc ^= request[i];
for (j = 0; j < 8; j++)
{
ushort flag = (ushort) (crc & 0X0001);
crc >>= 1; if (flag == 0) crc = (ushort) (crc ^ 0XA001);
}
}

// Set the CRC bytes in the request
request[num_to_write++] = (byte) (crc & 0X00FF);
request[num_to_write++] = (byte) ((crc & 0XFF00) >> 8);

// Send the request
if (!WriteFile(port, request, num_to_write, out uint _, IntPtr.Zero)) return false;

string text = request.ToString().Substring(0, (int) num_to_write).Replace("\r\n", " ");

// Flush the serial line
if (!FlushFileBuffers(port)) return false;

// Success
return true;
}

最佳答案

在 C# 等高级语言中,您不需要 sprintf 系列函数,因为它们通常允许使用简单的 =+= 进行字符串连接和赋值 运算符。

只需为其编写惯用的 C# 代码即可:

str = path + "\\SerialComms.ini";

评论者@itsme86 指出,对于构建路径的任务,您应该改为使用 Path.Combine :

Path.Combine(path, "SerialComms.ini");

关于c# - 如何在 C# 中模拟 C 函数 sprintf_s 的效果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56566300/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com