www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Trouble with ioctl and variadic arguments

reply nod <nod_member pathlink.com> writes:
I go nuts. The appended code works in C but not in D.
What am I doing wrong?

The D version fails on the ioctl call with errno
set to 14, or EFAULT, which means that the supplied
out pointer points to invalid memory.

I have tried other ways of allocating memory,
but since the result is the same I only write the
shortest way here, and it should work.
(68 is the sizeof of the real struct fb_fix_screeninfo)

I assume the problem lies in that ioctl takes variadic
parameters. Is there a correct way to deal with this,
or is this a compiler bug?

D version:
-----
import std.c.stdio; // for printf
import std.c.linux.linux; // for open, close
import std.c.stdlib; // for getErrno

extern (C)
{
// from /usr/include/sys/ioctl.h
int ioctl (int fd, ulong request, ...); 

// from /usr/include/linux/fb.h
const int FBIOGET_FSCREENINFO = 0x4602;
}

int main(char[][] args)
{
int fbd;
void* f = malloc(68);

if ( (fbd = open("/dev/fb0", O_RDWR)) == -1 )
printf("open() failed. errno == %i\n", getErrno());

if ( ioctl(fbd, FBIOGET_FSCREENINFO, f) != 0 )
printf("ioctl() failed. errno == %i\n", getErrno());

close(fbd);
return 0;
}
-----

C version:
-----
#include <errno.h> // for errno
#include <stdio.h> // for printf
#include <fcntl.h> // for O_RDWR
#include <sys/ioctl.h> // for ioctl
#include <linux/fb.h> // for FBIOGET_SCREENINFO

int main(void)
{
int fbd;
void* f = malloc(68);

if ( (fbd = open("/dev/fb0", O_RDWR)) == -1 )
printf("open() failed. errno == %i\n", errno);

if ( ioctl(fbd, FBIOGET_FSCREENINFO, f) != 0 )
printf("ioctl() failed. errno == %i\n", errno);

close(fbd);
return 0;
}
-----
Mar 14 2005
parent reply =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
nod wrote:
 I go nuts. The appended code works in C but not in D.
 What am I doing wrong?
 
 extern (C)
 {
 // from /usr/include/sys/ioctl.h
 int ioctl (int fd, ulong request, ...); 
 
 // from /usr/include/linux/fb.h
 const int FBIOGET_FSCREENINFO = 0x4602;
 }

Here is what my C header says:
 /* Perform the I/O control operation specified by REQUEST on FD.
    One argument may follow; its presence and type depend on REQUEST.
    Return value depends on REQUEST.  Usually -1 indicates error.  */
 extern int ioctl (int __fd, unsigned long int __request, ...) __THROW;

Remember that "long" translates to int in D, it is "long long" that translates to long... Thus it becomes: extern(C) int ioctl (int fd, uint request, ...); Another reason why we need a tool to translate these headers, instead of having to do it manually ? --anders
Mar 14 2005
parent nod <nod_member pathlink.com> writes:
In article <d144mn$1m3t$1 digitaldaemon.com>,
=?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= says...
Thus it becomes:
extern(C) int ioctl (int fd, uint request, ...);

Oww, that's a subtle one... I was actually scratching my head over why the D test program was pushing an extra dword onto the stack. Well it's obvious now isn't it? :)
Another reason why we need a tool to translate
these headers, instead of having to do it manually ?

Indeed. That would make the switch less painful. Oh, and thanks a million! //nod
Mar 14 2005