我非常了解C,而不是C ++ - 并且想要用C ++创建硬件驱动程序。我需要一些指示。
在C中,我将创建一个结构,使用函数指针并相应地填充func-pointers,在运行时填充ether,或者通过编译时初始化{就像在Linux内核驱动程序中重新初始化的设备驱动程序}。 Linux设备驱动程序通常有一个'driver private'元素,让驱动程序保持一个特定于实现的指针(保存其他东西)
我不知道该怎么做 - 使用C ++类创建相同的东西。
我的例子是串口。
驱动程序的硬件部分 - 在C中将是这样的:
struct serail_driver;
struct serial_hw_level;
struct serial_hw_level {
// points to implementation specific details
inptr_t hw_private;
// basically pure virtual functions
int (*wrBytes)( struct serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes );
int (*rdBytes)( struct serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes );
/* there would be other member funds, but this is is a short example */
};
/* the generic serial port */
struct serial_generic_driver {
const char *name;
struct serial_hw_driver *hw_Driver;
};
/* create two serial ports at the hardware level */
struct serial_hw_level arm9_serial_port = {
.hw_private = (intptr_t)(&hw_driver_
.wr_bytes = arm9_uart_wr_bytes,
.rd_bytes = arm9_uart_rd_bytes
};
struct serial_hw_level usb_emulated_port = {
.hw_private = (inptr_t)(&usb_private_stuff),
.wr_bytes = usb_serial_wr_bytes,
.rd_bytes = usb_serial_rd_bytes
};
/* create generic serial port stuff */
struct serial_port usb_serial = {
.name = "USBSERIAL",
.hw_driver = &usb_emulated_port
};
struct serial_port hw_serial = {
.name = "HW SERIAL",
.hw_driver = &arm9_serial_port
};
要清楚;我确实需要两个不同的抽象层次。我知道如何在直接C中执行此操作 - 在Linux内核中 - 这是一个蛋糕行走。
我不知道该怎么做是使用C ++处理额外的硬件特定内容,这些内容将保留在私有数据结构中。看来应该是派生类还是什么?
我在想这样的事情:
/* the base class */
class serial_hw_level {
intptr_t hw_private;
virtual int wr_bytes( uint8_t *pBytes, int bytes );
virtual int rd_bytes( uint8_t *pBytes, int bytes );
};
/* The generic usb serial port... */
class serial_port : public serial_hw_level {
string name;
};
/* another derived class */
class usb_serial : public serial_hw_level {
int usb_endpoint;
int usb_controller;
int emualted_handshake_pins;
};
所以我有一个类的VEN图,我的问题是如何在C ++中做到这一点。我可以用C做到这一点,很简单。我完全理解这种技巧。
我所拥有的是需要指向同一基类的两种类型的指针。
在普通的C中,我通过'intptr_t private'隐藏了一个特定于实现的结构 - 这是一个隐藏的指针。
在C ++中,我认为它保存在派生类中。
同样的想法可以扩展 - 我可以创建一个'ByteStream'类 - 它可以处理一个字节流 - 无论是文件,还是串行端口,或者 - 也许是内存中的缓冲区。
请注意:我使用串行端口作为示例,但这些也适用于I2C端口。我可能有一个以硬件实现的I2C端口,或者可能通过bit-bang IO或SPI端口实现
感谢。
答案 0 :(得分:2)
struct serial_driver;
class serial_hw_level {
public:
virtual ~serial_hw_level() { }
virtual int wrBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes) = 0;
virtual int rdBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes) = 0;
};
class arm9_uart: public serial_hw_level {
public:
arm9_uart(int sutff);
virtual ~arm9_uart();
virtual int wrBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes);
virtual int rdBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes);
private:
int arm9_stuff;
};
class usb_emulated: public serial_hw_level {
public:
usb_emulated(int endpoint, int controller, int handshake_pins);
virtual ~usb_emulated();
virtual int wrBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes);
virtual int rdBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes);
private:
int usb_endpoint;
int usb_controller;
int emulated_handshake_pins;
};
class serial_port {
public:
serial_port(const string& serial_name, serial_hw_level* driver);
~serial_port();
string get_name() const;
private:
string name;
serial_hw_level* hw_driver;
};
// Implementation *.cpp files
arm9_uart::arm9_uart(int stuff)
: arm9_stuff(stuff) {
}
arm9_uart::~arm9_uart() {
// free resources
}
int arm9_uart::wrBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes) {
// do things
return 0;
}
int arm9_uart::rdBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes) {
// do things
return 0;
}
usb_emulated::usb_emulated(int endpoint, int controller, int handshake_pins)
: usb_endpoint(endpoint),
usb_controller(controller),
emulated_handshake_pins(handshake_pins) {
}
usb_emulated::~usb_emulated() {
// free resources
}
int usb_emulated::wrBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes) {
// do things
return 0;
}
int usb_emulated::rdBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes) {
// do things
return 0;
}
serial_port::serial_port(const string& serial_name, serial_hw_level* driver)
: name(serial_name),
hw_driver(driver) {
}
serial_port::~serial_port() {
delete hw_driver;
hw_driver = NULL;
}
string serial_port::get_name() const {
return name;
}
serial_port hw_serail = {
"HW SERIAL",
new arm9_uart(arm9_stuff)
};
serial_port usb_serial = {
"USBSERIAL",
new usb_emulated(usb_endpoint, usb_controller, emulated_handshake_pins)
};
serial_hw_level是接口类。 C中的函数指针赋值如wrBytes在创建对象时通过虚函数指针在C ++中完成。
但是,serial_port类不必从serial_hw_level派生。组合更适合它,因为你需要一个名称,还有一个抽象的serial_hw_level对象。
接下来是全局命名空间中的对象。如果希望它是全局的,在C中,您可以简单地为它指定函数指针。您甚至没有派生类或派生对象。你所拥有的只是初始时的基类,基础对象和虚函数指针赋值(在C ++的视图中)。在C ++中,当您派生类和虚函数指针时,通过指针或引用实现对基类的赋值。由于您需要全局对象,您可以新建派生对象,在初始时将它们分配给基指针,并在进程由类serial_port的析构函数自动退出之前删除它们。