如何解决我应该如何将此C函数指针结构移植到C#.NET实现
我正在将通常使用C / C ++ for WIN32编写的引导加载程序宿主库移植到C#类库(而不是必须与原始库一起使用interop,希望可以更轻松地使用和调试) )。作为对OOP不太熟悉的人,我正在尝试找出如何将库的此特定功能实现为C#.NET(VS2019,.NET Standard 2.0)
typedef struct
{
/* Function used to open the communications connection */
int (*OpenConnection)(void);
/* Function used to close the communications connection */
int (*CloseConnection)(void);
/* Function used to read data over the communications connection */
int (*ReadData)(uint8_t*,int);
/* Function used to write data over the communications connection */
int (*WriteData)(uint8_t*,int);
/* Value used to specify the maximum number of bytes that can be transfered at a time */
unsigned int MaxTransferSize;
} CommunicationsData;
static CommunicationsData* g_comm;
int Bootloader_TransferData(uint8_t* inBuf,int inSize,uint8_t* outBuf,int outSize)
{
int err = g_comm->WriteData(inBuf,inSize);
if (CYRET_SUCCESS == err)
err = g_comm->ReadData(outBuf,outSize);
if (CYRET_SUCCESS != err)
err |= CYRET_ERR_COMM_MASK;
return err;
}
这个想法是库本身与通信协议无关,并且使用该库的应用程序是您编写OpenConnection()/ CloseConnection()/ ReadData()/ WriteData()的实现并提供值的地方用于MaxTransferSize。在将原始C库与互操作一起使用的C#应用程序中,操作如下:
class Bootloader_Utils{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int OpenConnection();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int CloseConnection();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int ReadData(IntPtr buffer,int size);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int WriteData(IntPtr buffer,int size);
/// <summary>
/// Structure used to pass communication data down to the unmanged native C code
/// that handles the bootloading operations.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct CommunicationsData
{
/// <summary>
/// Function used to open the communications connection
/// </summary>
public OpenConnection OpenConnection;
/// <summary>
/// Function used to close the communications connection
/// </summary>
public CloseConnection CloseConnection;
/// <summary>
/// Function used to read data over the communications connection
/// </summary>
public ReadData ReadData;
/// <summary>
/// Function used to write data over the communications connection
/// </summary>
public WriteData WriteData;
/// <summary>
/// Value used to specify the maximum number of bytes that can be transferred at a time
/// </summary>
public uint MaxTransferSize;
};
}
然后,您将在应用程序代码中创建一个新的CommunicationsData对象并分配方法:
Bootload_Utils.CommunicationsData comm_data = new Bootload_Utils.CommunicationsData();
comm_data.OpenConnection = OpenConnection;
comm_data.CloseConnection = CloseConnection;
comm_data.ReadData = ReadData;
comm_data.WriteData = WriteData;
comm_data.MaxTransferSize = 64;
然后在C#应用程序中定义这些方法,例如本例中的OpenConnection():
public int OpenConnection()
{
int status = (int)ReturnCodes.CYRET_SUCCESS;
if (ConnectionStatus == false)
{
try
{
serialPort.open();
ConnectionStatus = true;
}
catch (Exception exc)
{
ConnectionStatus = false;
SetText(tb_StatusLog," Error in opening serial port: " + exc.Message + "\r\n");
serialPort.Close();
}
}
return status;
}
如何在C#中复制此行为?我的想法是这样的:
public class CommunicationData
{
delegate int OpenConnection();
delegate int CloseConnection();
delegate int ReadData(ref byte[] dataBuf,int numBytes);
delegate int WriteData(ref byte[] dataBuf,int numBytes);
int MaxTransferSize { get; set; }
}
CommunicationData g_Comm = new CommunicationData();
int err = g_Comm.OpenConnection();
但这不是很正确,因为它仍然需要OpenConnection()的定义,我想将其定义在Application中,而不是在库中。
解决方法
如果在编写时由应用程序提供OpenConnection
,则使用delegate
可能是正确的方法。然后,您需要在应用程序中定义这些方法并填充结构。
或者,可以将CommunicationData
设置为应用程序或某些其他类需要实现的interface
,然后将 that 传递给库函数。或者也许将一个库包装在一个类中(其中g_comm
成为一个字段),然后仅将接口传递给其构造函数。
我同意@numzero,这可能是您正在寻找的接口。但是,如果您想更接近原始实现,则:
public class CommunicationData
{
public Func<int> OpenConnection { get; set; }
//etc
int MaxTransferSize { get; set; }
}
您可以这样做:
var data = new CommunicationData();
data.OpenConnection = OpenConnection;
data.OpenConnection();
使用界面
//in your lib
public interface ICommunicationData
{
int OpenConnection();
int CloseConnection();
int ReadData(byte[] dataBuf,int numBytes);
int WriteData(byte[] dataBuf,int numBytes);
int MaxTransferSize { get; set; }
}
//in your app
public class SerialCommunicationData : ICommunicationData
{
public int MaxTransferSize { get; set; }
public int CloseConnection()
{
return 1;
}
public int OpenConnection()
{
return 1;
}
public int ReadData(byte[] dataBuf,int numBytes)
{
return 1;
}
public int WriteData(byte[] dataBuf,int numBytes)
{
return 1;
}
}
public class UsbCommunicationData : ICommunicationData
{
public int MaxTransferSize { get; set; }
public int CloseConnection()
{
return 1;
}
public int OpenConnection()
{
return 1;
}
public int ReadData(byte[] dataBuf,int numBytes)
{
return 1;
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。