我对D非常陌生,我有C++背景。
我想试着用using发送SCSI CDBs。在D中是否有一个类允许我在Windows中打开一个与Windows CreateFile函数类似的本地设备?我也在寻找类似于T的D类东西。
有什么我可以玩的主意吗?如果D不能这样做,我知道我可以编写C++代码并从D链接到它。
发布于 2014-09-17 12:57:06
您可以直接调用CreateFile函数(尽管您可能需要使用CreateFileA或CreateFileW,因为D并不总是像C++那样定义方便的名称)。有三种方法:
1) D下载中包含了一些操作系统报头。import core.sys.windows.windows;将适用于CreateFileA (或W,这是宽字符(unicode)版本)。WriteFile以及许多其他基本功能也在其中。
对于Unix,import core.sys.posix.unistd;和朋友可以提供帮助。如果在C中使用#include <foo.h>,请在D中使用import core.sys.posix.foo;。
2)与D一起提供的Windows头实际上是最小的。您可以尝试从这里下载更多完整的https://github.com/AndrejMitrovic/DWinProgramming/tree/master/WindowsAPI
对于其他库,尝试在这里快速搜索,也许您也会发现绑定( http://code.dlang.org/ )
3)如果失败,可以将函数和结构定义从C复制/粘贴到D中。例如,如果需要ReadFileEx,就会发现它不在core.sys.windows.windows中。只需将以下内容添加到您的文件中,就可以调用它:
extern(Windows)
BOOL ReadFileEx(HANDLE, LPVOID, DWORD, OVERLAPPED*, void*);您可以从MSDN获得的定义,删除一些额外的宏等等。而不是编写WINAPI,而是编写extern(Windows),那么大部分函数都是相同的。(尽管如此,仍然要导入core.sys.windows.windows,这样您就有了DWORD之类的东西的定义。)
然后您就可以正常地调用该函数了。您还可以从其他库为Unix函数执行extern(C)。但是,在C中看到c_long和unsigned long时,一定要使用long和unsigned long,因为它们不一定与D中的long相同。
类似地,可以根据需要将结构复制/粘贴到D中,并使其可用,同样,只需将成员类型转换为等效的D,并确保它们保持相同的顺序。提示:如果结构总是由指针来使用,那么只需传递void*而不是实际的定义就可以了。你失去了一些类型的安全,但它经常起作用。
发布于 2014-09-21 02:43:34
补充一下亚当的答案:
从DMD 2.066开始,您可以使用函数windowsHandleOpen将任何HANDLE (通过CreateFile获得)与std.stdio.File相关联。这应该允许您对任意的Windows对象(设备、管道等)使用D的std.stdio。
发布于 2014-09-21 07:58:55
在Adam的帮助下,我想出了下面的代码(重写这个):
import core.sys.posix.sys.ioctl : ioctl;
import core.stdc.errno : errno;
import std.stdio : write, writef, writeln, writefln, File;
import std.xml : isChar;
const int SG_IO = 0x2285;
const int SG_DXFER_FROM_DEV = -3;
const uint SG_INFO_OK_MASK = 1;
const uint SG_INFO_OK = 0;
const uint INQ_LEN = 6;
struct _sg_io_hdr
{
int interface_id; /* [i] 'S' for SCSI generic (required) */
int dxfer_direction; /* [i] data transfer direction */
ubyte cmd_len; /* [i] SCSI command length ( <= 16 bytes) */
ubyte mx_sb_len; /* [i] max length to write to sbp */
ushort iovec_count; /* [i] 0 implies no scatter gather */
uint dxfer_len; /* [i] byte count of data transfer */
void * dxferp; /* [i], [*io] points to data transfer memory
or scatter gather list */
ubyte * cmdp; /* [i], [*i] points to command to perform */
ubyte * sbp; /* [i], [*o] points to sense_buffer memory */
uint timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */
uint flags; /* [i] 0 -> default, see SG_FLAG... */
int pack_id; /* [i->o] unused internally (normally) */
void * usr_ptr; /* [i->o] unused internally */
ubyte status; /* [o] scsi status */
ubyte masked_status;/* [o] shifted, masked scsi status */
ubyte msg_status; /* [o] messaging level data (optional) */
ubyte sb_len_wr; /* [o] byte count actually written to sbp */
ushort host_status; /* [o] errors from host adapter */
ushort driver_status;/* [o] errors from software driver */
int resid; /* [o] dxfer_len - actual_transferred */
uint duration; /* [o] time taken by cmd (unit: millisec) */
uint info; /* [o] auxiliary information */
} /* 64 bytes long (on i386) */
void writeBuffer(char[] buff, int length)
{
for (int k = 0; k < buff.length; ++k)
{
if ((k > 0) && (0 == (k % 8)))
{
writeln();
}
// breaks output of non-chars in char range, but who cares in this code
if (isChar(buff[k]))
{
write(" ", cast(char)(buff[k]), " ");
}
else
{
writef("%02x ", buff[k]);
}
}
}
int main()
{
_sg_io_hdr io_hdr;
char[INQ_LEN] cdb = 0;
char[32] senseBuffer = 0;
char[96] inqBuffer = 0;
cdb[0] = 0x12;
cdb[4] = cdb.length;
io_hdr.interface_id = 'S';
io_hdr.cmd_len = cdb.length;
io_hdr.cmdp = cast(ubyte*)(cdb);
io_hdr.mx_sb_len = senseBuffer.length;
io_hdr.sbp = cast(ubyte*)(senseBuffer);
io_hdr.dxfer_len = inqBuffer.length;
io_hdr.dxferp = cast(ubyte*)(inqBuffer);
io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
io_hdr.timeout = 5000;
auto file = File("/dev/sdb", "rb");
int res = ioctl(file.fileno(), SG_IO, &io_hdr);
file.close();
if (res < 0)
{
writeln("ERROR: inquiry SG_IO ioctl error ", errno);
}
if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK)
{
writeln("ERROR: io_hdr.info is not OK");
}
writefln("INQUIRY duration=%u millisecs, resid=%d\n",
io_hdr.duration, io_hdr.resid);
writeln("INQUIRY inquiry buffer: ");
writeBuffer(inqBuffer, inqBuffer.length);
writeln("\n");
return 0;
}https://stackoverflow.com/questions/25882682
复制相似问题