D在Windows / Linux上打开本机设备

时间:2014-09-17 05:06:39

标签: d

我对D很新,我有C ++背景。

我想尝试使用D lang发送SCSI CDB。 D中是否有类允许我在Windows中打开类似于Windows CreateFile函数的本机设备?我也在寻找与sg_io_hdr_t类似的D东西。

我可以玩的任何想法?如果D不能这样做,我知道我可以编写C ++代码并从D链接到它。

3 个答案:

答案 0 :(得分:2)

您可以直接调用Windows CreateFile函数(尽管您可能需要使用CreateFileACreateFileW,因为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_ulonglong,因为它们不一定与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;
}
相关问题