我对D很新,我有C ++背景。
我想尝试使用D lang发送SCSI CDB。 D中是否有类允许我在Windows中打开类似于Windows CreateFile函数的本机设备?我也在寻找与sg_io_hdr_t类似的D东西。
我可以玩的任何想法?如果D不能这样做,我知道我可以编写C ++代码并从D链接到它。
答案 0 :(得分:2)
您可以直接调用Windows 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
,你会发现它不在{{1}中}。您可以通过将其添加到您的文件来调用它:
core.sys.windows.windows
您可以从MSDN获取的定义,以及一些额外的宏等已删除。您编写 extern(Windows)
BOOL ReadFileEx(HANDLE, LPVOID, DWORD, OVERLAPPED*, void*);
而不是WINAPI
,而大多数函数的其余部分都是相同的。 (确保仍然导入core.sys.windows.windows,所以你有像DWORD这样的东西的定义。)
然后你可以正常调用该函数。对于其他库中的Unix函数,您也可以extern(Windows)
。当你在C中看到extern(C)
和c_long
时,请务必使用c_ulong
和long
,因为它们不一定与D中的unsigned long
相同。这些类型可在long
中找到。
类似地,结构可以根据需要复制/粘贴到D中并且可用,再次,只需将成员类型转换为等效的D,确保它们保持相同的顺序。提示:如果结构总是仅由指针使用,那么您可能只需要传递import core.stdc.config;
而不是实际定义。你失去了一些类型的安全性,但它经常有效。
答案 1 :(得分:1)
添加到Adam的答案:
从DMD 2.066开始,您可以使用windowsHandleOpen
功能将任何Windows HANDLE
(通过CreateFile
获得)与std.stdio.File
相关联。这应该允许你将D'std.stdio
与任意Windows句柄对象(设备,管道等)一起使用。
答案 2 :(得分:0)
在Adam的帮助下,我想出了这段代码(rewrite of this):
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;
}