我正在从C ++调用ioctl
调用一个我不拥有/维护的驱动程序,而我正试图弄清楚是否有一个干净的,“安全的”机制来处理一些需要的丑陋结构分配。
涉及一些结构的简化版本
// IOCTL expects an instance of this structure "first"
typedef struct {
int param1;
int param2;
} s_ioctl_request;
//... followed by an instance of this. If attr_length
// is > sizeof(s_attr_header), more data is allowed to follow.
typedef struct {
uint32_t attr_length;
uint32_t attr_type;
} s_attr_header;
// Example that uses more data than just the header.
typedef struct {
s_attr_header hdr;
uint32_t attr_param;
} s_attr_type1;
// Another example.
typedef struct {
s_attr_header hdr;
uint32_t attr_param1;
uint32_t attr_param2;
} s_attr_type2;
ioctl要求s_ioctl_request
后面紧跟s_attr_header
或其他包含它的结构,其中attr_length
设置为外部结构的大小(以字节为单位)。
在C
中,要为ioctl
编写包装器,可以通过以下方式完成:
int do_ugly_ioctl(int fd, int p1, int p2, s_attr_header * attr)
{
int res;
// Allocate enough memory for both structures.
s_ioctl_request *req = malloc( sizeof(*req) + attr->hdr.attr_length );
// Copy the 2nd, (variable length) structure after the first.
memcpy( ((char*)req) + sizeof(*req), attr, attr->hdr.attr_length);
// Modify params as necessary
req->param1 = p1;
req->param2 = p2;
// Make the driver call, free mem, and return result.
res = ioctl(fd, SOME_IOCTL_ID, req);
free(req);
return res;
}
// Example invocation.
s_attr_type1 a1;
a1.hdr.attr_length = sizeof(a1);
a1.hdr.attr_type = 1;
do_ugly_ioctl(fd, 10, 20, &a1);
我想到的几个选项是:
抛出现代C ++ - 窗外的主义,并完全按照我上面所示的那样做。
使用std :: vector分配存储,然后使用生成的std :: vector :: data()指针进行丑陋的转换,这样至少我没有new[]
/ {{1 }}或delete[]
/ malloc
。
为使用自己的“特殊”结构的每个free
创建一个唯一的包装器方法。这似乎是“最安全的”,即包装方法的用户最不可能将其搞砸。和奖励积分,允许传递参考。
方法#3示例:
s_attr_type*
所以我想这里的一些问题是:
对C ++来说“值得吗” - 找到解决这个问题的方法吗? (而不是依赖于更易出错的C impl)。
如果我使用方法#3或类似方法,我可以使用int do_ugly_ioctl(fd, int param1, int param2, s_attr_type2& attr){
struct RequestData {
s_ioctl_request ioreq;
s_attr_type2 attr;
};
RequestData r;
r.ioreq.param1 = param1;
r.ioreq.param2 = param2;
r.attr = attr;
r.attr.hdr.attr_length = sizeof(attr); // Might as well enforce this here.
ioctl(fd, SOME_IOCTL_ID, (void*) &r);
}
制作此函数的模板,并仅接受<type_traits>
作为第一个的结构构件?
还有其他精彩的想法吗?
答案 0 :(得分:3)
完全值得,你的解决方案非常好。
您可能希望将结构声明为import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.*;
public class TimerPanel extends JPanel{
private int min,sec;
private String theTime = min + ":" + sec;
private int width=350, height=300;
private boolean timerStarted=false;
private Timer swingTimer = new Timer(900, new ActionListener(){
public void actionPerformed(ActionEvent event){
if(sec<60){
sec++;
repaint();
}else{
min++;
sec=0;
repaint();
}
}
});
//Constructor
public TimerPanel(){
setPreferredSize(new Dimension(350,300));
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//start the timer
public void startTimer(){
swingTimer.start();
}
//Stop the timer
public void stopTimer(){
swingTimer.stop();
}
//reset the timer
public void resetTimer(){
sec=0; min=0;
repaint();
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//Paint Method
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.WHITE);
g.setFont(new Font("Arial", Font.PLAIN, 40));
g.drawString(theTime, width/2-45, height/2);
setBackground(Color.BLACK);
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
}
(有实现此目的的编译器扩展),以避免在组合多个结构时有额外的填充。
您还可以在构造函数中设置结构的大小。
packed
关于你的第二个问题,你可以将赋值分成两部分,它不是太好但是很容易,如果你传递的东西没有正确的标题,就会导致编译错误:
struct RequestData
{
RequestData() : ioreq{}, attr{}
{
attr.hdr.attr_length = sizeof(attr);
}
s_ioctl_request ioreq;
s_attr_type2 attr;
};