www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Converting Fuse headers

reply Jesse Phillips <jessekphillips+D gmail.com> writes:
I'm trying to make fuse work in D[1]. I had some help from htod, but not
everything was successful. And I'm not exactly sure how to properly convert
strings and such.

What I currently have allows me to compile some fuse programs (hello for
example[2]). But the result is a dead link (only seem to be able to fix it by
rebooting). Anyway the specific questions I want to get out of the way are as
follows.

hello_str = cast(char*) toStringz("Hello World!\n");

I stopped doing this, but I'm just wondering how you could get a modifiable C
string if I needed one?

fuse.d:669 auto user_data = new ubyte[78];
fuse.d:670 return fuse_main_real(cast(int) argc, argv, op, (*(op)).sizeof,
user_data.ptr);

[3]This is likely a big part of the problem, but I just didn't understand the
C. It is a defined as:

#define fuse_main(argc, argv, op, user_data)				\
	fuse_main_real(argc, argv, op, sizeof(*(op)), user_data)

But is called:

return fuse_main(argc, argv, &hello_oper);

And I can't find a three argument fuse_main. So I made one and just passed a
block of storage (converting to a pointer so the compiler wouldn't complain of
conversions and I didn't cast)

Then there is a structure which had some padding, and htod didn't fully convert
it, leaving off two fields at the end[4]. Maybe I should move them to just
after the bit field? I think it would be fine...

The last one is the node structure[5]. Which I found in fuse.c[6] but seems to
be used a lot so I don't no why it isn't in a header. This used the is_hidden :
1 notation so I created some bit fields, but it didn't have padding like the
others, so I don't know if I did this correctly.

This is probably trivial bindings for those who know C better, but it has been
fun. The links are below, and I was using the 2.8.4 header files.

1. https://github.com/he-the-great/Fused
2. http://fuse.sourceforge.net/helloworld.html
3. https://github.com/he-the-great/Fused/blob/master/fuse.d#L663
4. https://github.com/he-the-great/Fused/blob/master/fuse_common.d#L95
5. https://github.com/he-the-great/Fused/blob/master/fuse_helper.d#L54
6. https://github.com/he-the-great/Fused/blob/master/fuse.c#L113
Nov 06 2010
next sibling parent reply Jesse Phillips <jessekphillips+D gmail.com> writes:
Jesse Phillips Wrote:

 I'm trying to make fuse work in D[1]. I had some help from htod, but not
everything was successful. And I'm not exactly sure how to properly convert
strings and such.
When saying D[1], I was referencing the link, not the version of D. But otherwise no suggestions?
Nov 08 2010
parent reply div0 <div0 sourceforge.net> writes:
On 09/11/2010 05:49, Jesse Phillips wrote:
 Jesse Phillips Wrote:

 I'm trying to make fuse work in D[1]. I had some help from htod, but not
everything was successful. And I'm not exactly sure how to properly convert
strings and such.
When saying D[1], I was referencing the link, not the version of D. But otherwise no suggestions?
Well I don't like to discourage people, but a casual glance at your post and the fuse headers suggests to me you don't have nearly enough experience of C to succeed. By the time anybody finishes answering all your questions they'd have spent less time just porting the stuff themselves. If you want to port C headers you need to rack up a few months of programming in C first. -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
Nov 09 2010
parent Jesse Phillips <jessekphillips+D gmail.com> writes:
div0 Wrote:

 Well I don't like to discourage people, but a casual glance at your post 
 and the fuse headers suggests to me you don't have nearly enough 
 experience of C to succeed.
Thank you for the input. And I already figured quit a bit of effort would go into answering. I considered asking in a C related forum, but I don't exactly know what "C question" I'm asking.
 By the time anybody finishes answering all your questions they'd have 
 spent less time just porting the stuff themselves.
 
 If you want to port C headers you need to rack up a few months of 
 programming in C first.
Well, I do have that much C experience, but I suppose you're referring to more than personal/class projects. In truth I wasn't hoping necessarily for an answer, but good old, "You're doing it wrong" would actually be very helpful. I did attempt to solve the problem and these where the only areas I think something was wrong.
Nov 09 2010
prev sibling next sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Jesse Phillips <jessekphillips+D gmail.com> wrote:

 hello_str = cast(char*) toStringz("Hello World!\n");

 I stopped doing this, but I'm just wondering how you could get a  
 modifiable C string if I needed one?
If you already have a char[], just make sure it's terminated with a zero ('\0') character, and you can use yourCharArray.ptr to get the char*. If it is not zero-terminated, either append a '\0' to it, or, if that can't or shouldn't be done, .dup it, and append a '\0' to the copy. If you have an immutable(char)[] (i.e. string), and you want to change the contents of it, you should check your code. :p In such a case, use char[] instead, and make sure to .dup any literals, as those are placed in the static data segment and may be write-protected. If you have a string and you want to create a mutable copy, use .dup. If some of the C functions expect a char*, check the documentation to see if it should take a const(char)* instead.
 fuse.d:669 auto user_data = new ubyte[78];
 fuse.d:670 return fuse_main_real(cast(int) argc, argv, op,  
 (*(op)).sizeof, user_data.ptr);

 [3]This is likely a big part of the problem, but I just didn't  
 understand the C. It is a defined as:

 #define fuse_main(argc, argv, op, user_data)				\
 	fuse_main_real(argc, argv, op, sizeof(*(op)), user_data)

 But is called:

 return fuse_main(argc, argv, &hello_oper);

 And I can't find a three argument fuse_main. So I made one and just  
 passed a block of storage (converting to a pointer so the compiler  
 wouldn't complain of conversions and I didn't cast)
All other places I've looked seem to add a NULL at the end. Could be that's done automagically otherwise, but I would not bet on it.
 Then there is a structure which had some padding, and htod didn't fully  
 convert it, leaving off two fields at the end[4]. Maybe I should move  
 them to just after the bit field? I think it would be fine...
My guess is it somehow got confused by the bitfield. Should be fine just adding it as you say. All those functions manipulating the bitfield should be marked as property, btw.
 The last one is the node structure[5]. Which I found in fuse.c[6] but  
 seems to be used a lot so I don't no why it isn't in a header.
Lemme guess, usually just the pointer is used? If so, it's hiding the implementation. Just an indication you should never need to touch the innards of the node.
 This used the is_hidden : 1 notation so I created some bit fields, but  
 it didn't have padding like the others, so I don't know if I did this  
 correctly.
Looks right to me. -- Simen
Nov 09 2010
parent reply Jesse Phillips <jessekphillips+D gmail.com> writes:
Simen kjaeraas Wrote:

 The last one is the node structure[5]. Which I found in fuse.c[6] but  
 seems to be used a lot so I don't no why it isn't in a header.
Lemme guess, usually just the pointer is used? If so, it's hiding the implementation. Just an indication you should never need to touch the innards of the node.
Thank you so much. This is the only one I have a follow up question. I'm going to test this question when I get home, but just in case it doesn't work. In the header file it declares two structures. On of them being fuse /** Handle for a FUSE filesystem */ struct fuse; Can you forward declare a reference like this in D? If not does it matter what I define it to be? struct fuse {} // Since I'm really only passing pointers to this anyway. Sure hope this makes it work.
 Jesse Phillips <jessekphillips+D gmail.com> wrote:
 
 hello_str = cast(char*) toStringz("Hello World!\n");

 I stopped doing this, but I'm just wondering how you could get a  
 modifiable C string if I needed one?
If you already have a char[], just make sure it's terminated with a zero ('\0') character, and you can use yourCharArray.ptr to get the char*.
...
 If some of the C functions expect a char*, check the documentation
 to see if it should take a const(char)* instead.
Thanks, I had been using ".".dup.ptr in a couple places so, I was a little bit iffy then realized const(char*) actually worked for most of them. Otherwise I don't want to assume the parameter is const.
 
 fuse.d:669 auto user_data = new ubyte[78];
 fuse.d:670 return fuse_main_real(cast(int) argc, argv, op,  
 (*(op)).sizeof, user_data.ptr);
All other places I've looked seem to add a NULL at the end. Could be that's done automagically otherwise, but I would not bet on it.
Thanks. I don't know why I thought I should give it data.
 
 Then there is a structure which had some padding, and htod didn't fully  
 convert it, leaving off two fields at the end[4]. Maybe I should move  
 them to just after the bit field? I think it would be fine...
My guess is it somehow got confused by the bitfield. Should be fine just adding it as you say.
Yeah, thinking about it some, I don't know how functions affect the structure, so I'll move the fields before the functions.
Nov 09 2010
parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Jesse Phillips <jessekphillips+D gmail.com> wrote:

 Can you forward declare a reference like this in D? If not does it  
 matter what I define it to be?

 struct fuse {} // Since I'm really only passing pointers to this anyway.

 Sure hope this makes it work.
It's completely safe to define it like that. Just don't do 'new fuse()' anywhere, as that would allocate the size of your empty struct. :p
 Yeah, thinking about it some, I don't know how functions affect the  
 structure, so I'll move the fields before the functions.
No changes in structure due to functions. It may be easier to read with functions at the end, though. -- Simen
Nov 09 2010
prev sibling parent reply Jesse Phillips <jessekphillips+D gmail.com> writes:
I have some good news! It works (Simplest test case). I spent several hours
trying to track down where my code translation could be causing problems. And
have concluded that core.sys.posix.sys.stat.stat_t is not correct for my 32bit
Debian Linux machine.

I realize this is a big claim, so I'm going to look into it some more. But to
get my code working I moved the getattr function into a C file and called that
instead of using it from D. I also noticed that the value set to stat_t.st_mode
would not be returned when requesting it back.

Thank you Simen and div0.

1. https://github.com/he-the-great/Fused
Nov 09 2010
parent reply div0 <div0 sourceforge.net> writes:
On 10/11/2010 06:21, Jesse Phillips wrote:
 I have some good news! It works (Simplest test case). I spent several hours
trying to track down where my code translation could be causing problems. And
have concluded that core.sys.posix.sys.stat.stat_t is not correct for my 32bit
Debian Linux machine.

 I realize this is a big claim, so I'm going to look into it some more. But to
get my code working I moved the getattr function into a C file and called that
instead of using it from D. I also noticed that the value set to stat_t.st_mode
would not be returned when requesting it back.

 Thank you Simen and div0.

 1. https://github.com/he-the-great/Fused
Well done, glad you proved me wrong. It does seem unlikely that size_t is wrong, though you can test it easily enough: compile a test C program to see what size it is and compare it to the D version: void main() { printf("sizeof: %d", sizeof(size_t)); } It should be 4 on a 32 bit system & 8 for 64 bit. -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
Nov 10 2010
parent reply Jesse Phillips <jessekphillips+D gmail.com> writes:
div0 Wrote:

 Well done, glad you proved me wrong.
 
 It does seem unlikely that size_t is wrong,
 though you can test it easily enough:
 
 compile a test C program to see what size it is and compare it to the D 
 version:
 
 void main() {
 	printf("sizeof: %d", sizeof(size_t));
 }
 
 It should be 4 on a 32 bit system & 8 for 64 bit.
Hope I didn't say size_t. stat_t, a very complicated struct known as struct stat in C. I don't know for sure that it is wrong, but at this point it is the most likely candidate. Also none of the changes I made related to the question affected the ability of the program to work (maybe a more complicated one). Just glad I wasn't to far off in my translation.
Nov 10 2010
parent reply div0 <div0 sourceforge.net> writes:
On 10/11/2010 20:15, Jesse Phillips wrote:
 div0 Wrote:

 Well done, glad you proved me wrong.

 It does seem unlikely that size_t is wrong,
 though you can test it easily enough:

 compile a test C program to see what size it is and compare it to the D
 version:

 void main() {
 	printf("sizeof: %d", sizeof(size_t));
 }

 It should be 4 on a 32 bit system&  8 for 64 bit.
Hope I didn't say size_t. stat_t, a very complicated struct known as struct stat in C. I don't know for sure that it is wrong, but at this point it is the most likely candidate. Also none of the changes I made related to the question affected the ability of the program to work (maybe a more complicated one). Just glad I wasn't to far off in my translation.
Sorry, me misreading. You can still do the size check for the stat_t struct as well, I always double check the size of structs when doing those conversions as it's very easy to get it wrong. -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
Nov 10 2010
parent reply Jesse Phillips <jessekphillips+D gmail.com> writes:
div0 Wrote:

 You can still do the size check for the stat_t struct as well,
 I always double check the size of structs when doing those conversions 
 as it's very easy to get it wrong.
Ah, good idea. The test I have planned will be to set some values in the D struct, and see what is read by the C struct. The size thing will definitely be a simple give away if it differs. I might try to use some reflection to see what the structure D creates looks like, so that it will be easier to compare the D code with the C header. (Lots of version statements in the D version, might be some macros in C too.)
Nov 10 2010
parent div0 <div0 sourceforge.net> writes:
On 10/11/2010 21:02, Jesse Phillips wrote:
 div0 Wrote:

 You can still do the size check for the stat_t struct as well,
 I always double check the size of structs when doing those conversions
 as it's very easy to get it wrong.
Ah, good idea. The test I have planned will be to set some values in the D struct, and see what is read by the C struct. The size thing will definitely be a simple give away if it differs. I might try to use some reflection to see what the structure D creates looks like, so that it will be easier to compare the D code with the C header. (Lots of version statements in the D version, might be some macros in C too.)
Also another thing to make life easier, use gcc's only preprocess the file option (-E ?) and save the result. That way you can look at the raw struct after all the CPP macros have been applied/stripped out. That's very handy with complicated C structs. -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk
Nov 10 2010