首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >D在Windows/Linux上打开本机设备

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

Stack Overflow用户
提问于 2014-09-17 05:06:38
回答 3查看 192关注 0票数 3

我对D非常陌生,我有C++背景。

我想试着用using发送SCSI CDBs。在D中是否有一个类允许我在Windows中打开一个与Windows CreateFile函数类似的本地设备?我也在寻找类似于T的D类东西。

有什么我可以玩的主意吗?如果D不能这样做,我知道我可以编写C++代码并从D链接到它。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-09-17 12:57:06

您可以直接调用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,就会发现它不在core.sys.windows.windows中。只需将以下内容添加到您的文件中,就可以调用它:

代码语言:javascript
复制
    extern(Windows)
            BOOL ReadFileEx(HANDLE, LPVOID, DWORD, OVERLAPPED*, void*);

您可以从MSDN获得的定义,删除一些额外的宏等等。而不是编写WINAPI,而是编写extern(Windows),那么大部分函数都是相同的。(尽管如此,仍然要导入core.sys.windows.windows,这样您就有了DWORD之类的东西的定义。)

然后您就可以正常地调用该函数了。您还可以从其他库为Unix函数执行extern(C)。但是,在C中看到c_longunsigned long时,一定要使用longunsigned long,因为它们不一定与D中的long相同。

类似地,可以根据需要将结构复制/粘贴到D中,并使其可用,同样,只需将成员类型转换为等效的D,并确保它们保持相同的顺序。提示:如果结构总是由指针来使用,那么只需传递void*而不是实际的定义就可以了。你失去了一些类型的安全,但它经常起作用。

票数 2
EN

Stack Overflow用户

发布于 2014-09-21 02:43:34

补充一下亚当的答案:

从DMD 2.066开始,您可以使用函数windowsHandleOpen将任何HANDLE (通过CreateFile获得)与std.stdio.File相关联。这应该允许您对任意的Windows对象(设备、管道等)使用D的std.stdio

票数 1
EN

Stack Overflow用户

发布于 2014-09-21 07:58:55

在Adam的帮助下,我想出了下面的代码(重写这个):

代码语言:javascript
复制
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;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25882682

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档