www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Recommended coding convention for combining unix and windows code ?

reply chmike <christophe meessen.net> writes:
Hello

I'm writing some code that I want to be portable across Posix and 
Windows.

What is the recommended code convention for such type of code ?

80% of the class implementation is the same for both OS.

Should I write the following and copy past the 80%

version( Windows ) {
     import core.sys.windows;
     class MyInfo {...}
} else version( Posix ) {
     import core.sys.posix;
     class MyInfo {...}
} else {
     static assert(false, "Unsupported platform");
}

or should I do it the C way with multiple embedded static if... ?

version( Windows ) {
     import core.sys.windows;
} else {  //Posix
     import core.sys.posix;
}

class MyInfo {
     ...
     static if(windows) {
     enum Value {...}
     } static else {  //Posix
     enum Value {...}
     }
     ...
}
Jun 07 2016
next sibling parent FreeSlave <freeslave93 gmail.com> writes:
On Tuesday, 7 June 2016 at 15:33:57 UTC, chmike wrote:
 Hello

 I'm writing some code that I want to be portable across Posix 
 and Windows.

 What is the recommended code convention for such type of code ?

 80% of the class implementation is the same for both OS.

 Should I write the following and copy past the 80%

 version( Windows ) {
     import core.sys.windows;
     class MyInfo {...}
 } else version( Posix ) {
     import core.sys.posix;
     class MyInfo {...}
 } else {
     static assert(false, "Unsupported platform");
 }

 or should I do it the C way with multiple embedded static if... 
 ?

 version( Windows ) {
     import core.sys.windows;
 } else {  //Posix
     import core.sys.posix;
 }

 class MyInfo {
     ...
     static if(windows) {
     enum Value {...}
     } static else {  //Posix
     enum Value {...}
     }
     ...
 }
I think there's no need for copy-paste approach in user code when the most parts are shared. Copy-pasting would eventually make classes out of sync in terms of function declarations (parameters, attributes) which in its turn will lead to unexpected bugs and errors when compiling on other platform. Also copy-pasting of class would require to copy-paste documentation comments and unittests, which is another PITA. You can write declarations specifically for documentation comments, but it means even more copy-pasting and can lead to the situation where documentation is out of sync with actual declarations. By the way phobos has example of copy-paste - DirEntry struct. And its functions have different attributes across Windows and Posix (e.g. const vs non-const) which really hurts cross-platform programming.
Jun 07 2016
prev sibling next sibling parent Johan Engelen <j j.nl> writes:
On Tuesday, 7 June 2016 at 15:33:57 UTC, chmike wrote:
 
 or should I do it the C way with multiple embedded static if...
In your example, `version` would also work instead of `static if`. I would not copy much code needlessly, and go with the embedded version/static ifs. - Johan
Jun 07 2016
prev sibling next sibling parent wobbles <grogan.colin gmail.com> writes:
On Tuesday, 7 June 2016 at 15:33:57 UTC, chmike wrote:
 Hello

 I'm writing some code that I want to be portable across Posix 
 and Windows.

 What is the recommended code convention for such type of code ?

 80% of the class implementation is the same for both OS.

 Should I write the following and copy past the 80%

 version( Windows ) {
     import core.sys.windows;
     class MyInfo {...}
 } else version( Posix ) {
     import core.sys.posix;
     class MyInfo {...}
 } else {
     static assert(false, "Unsupported platform");
 }

 or should I do it the C way with multiple embedded static if... 
 ?

 version( Windows ) {
     import core.sys.windows;
 } else {  //Posix
     import core.sys.posix;
 }

 class MyInfo {
     ...
     static if(windows) {
     enum Value {...}
     } static else {  //Posix
     enum Value {...}
     }
     ...
 }
I did something similar, and went with the c-style version (x) inside each code block. Have a look here for how it looks. https://github.com/grogancolin/dexpect/blob/master/source/dexpect.d
Jun 07 2016
prev sibling parent Olivier Pisano <olivier.pisano supersonicimagine.com> writes:
Hi,

I personally separate OS-specific implementations in modules with 
the same name, in different directories. From the filesystem 
perspective:

widget.d
linux/widgetimpl.d
windows/widgetimpl.d

 From the code perspective, the *impl modules would present 
homonymic types with the same public interface.

module widget;

class Widget
{
     version(Windows)
     {
         import windows.widgetimpl;
     }
     version(linux)
     {
         import linux.widgetimpl;
     }

     void systemSpecificTask()
     {
         auto s = SystemSpecificStruct(); // defined in every 
widgetimpl.d
         s.execute();
     }
}
Jun 08 2016