www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Using a C function with command line parameters

reply Jonathan Sternberg <jonathansternberg gmail.com> writes:
glut has the function:

    void glutInit( int* pargc, char** argv );

In order to use it. Since D has an ABI compatible with C, I should be able to
write a D file with extern (C) on the glut functions. How would I wrap this
function to be used with D arrays? Such as:

int main(string[] args)
{
    glutInit( /* I don't know what to do here */ );
    return 0;
}

Thanks.
Jul 04 2011
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 04 Jul 2011 10:31:58 -0400, Jonathan Sternberg  
<jonathansternberg gmail.com> wrote:

 glut has the function:

     void glutInit( int* pargc, char** argv );

 In order to use it. Since D has an ABI compatible with C, I should be  
 able to
 write a D file with extern (C) on the glut functions. How would I wrap  
 this
 function to be used with D arrays? Such as:

 int main(string[] args)
 {
     glutInit( /* I don't know what to do here */ );
     return 0;
 }

 Thanks.

Convert all the args to zero-terminated strings. One thing to look at, does glutInit actually modify any of the strings or does it just remove them from the argv array? Because I would expect the argv argument to be const(char)** if it doesn't modify. That would allow you to pass in the strings without having to duplicate them. Some untested code: auto argarr = new immutable(char)*[args.length]; foreach(i, a; args) argarr[i] = (a.dup ~ '\0').ptr; int argc = argarr.length; glutInit(&argc, argarr.ptr); // now, need to refix args to ignore arguments already consumed by glutInit ... -Steve
Jul 04 2011
parent Jonathan Sternberg <jonathansternberg gmail.com> writes:
It's one of the applications that consumes command line arguments. So if I
wanted
to implement this, a copy of the D strings (and null terminated) would have to
be
made. I would also likely need to add another slot to the command line arguments
as usually the command line is null terminated for C programs.

Generally, command line arguments don't modify the parameters. But C isn't
particularly good at using const correctness.

A wrapper around glutInit would require copying the array to a C-style array,
calling the extern (C)'d function, then copying back the changes to the D side
back to a D style array. Right?
Jul 04 2011
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 04 Jul 2011 10:39:07 -0400, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:

 On Mon, 04 Jul 2011 10:31:58 -0400, Jonathan Sternberg  
 <jonathansternberg gmail.com> wrote:

 glut has the function:

     void glutInit( int* pargc, char** argv );

 In order to use it. Since D has an ABI compatible with C, I should be  
 able to
 write a D file with extern (C) on the glut functions. How would I wrap  
 this
 function to be used with D arrays? Such as:

 int main(string[] args)
 {
     glutInit( /* I don't know what to do here */ );
     return 0;
 }

 Thanks.

Convert all the args to zero-terminated strings. One thing to look at, does glutInit actually modify any of the strings or does it just remove them from the argv array? Because I would expect the argv argument to be const(char)** if it doesn't modify. That would allow you to pass in the strings without having to duplicate them. Some untested code: auto argarr = new immutable(char)*[args.length];

bleh, this should have been new char*[args.length]; Sorry. -Steve
Jul 04 2011
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2011-07-04 16:31, Jonathan Sternberg wrote:
 glut has the function:

      void glutInit( int* pargc, char** argv );

 In order to use it. Since D has an ABI compatible with C, I should be able to
 write a D file with extern (C) on the glut functions. How would I wrap this
 function to be used with D arrays? Such as:

 int main(string[] args)
 {
      glutInit( /* I don't know what to do here */ );
      return 0;
 }

 Thanks.

It depends on what your needs are. If your not actually using the arguments then you can pass in 0 and null, or 1 and the name of the application. As an alternative, most platforms have an API for getting the arguments passed to an application. Mac OS X: extern (C) char*** _NSGetEnviron(); Posix: extern (C) extern char** environ; Don't know about Windows. -- /Jacob Carlborg
Jul 04 2011
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 04 Jul 2011 12:51:48 -0400, Jacob Carlborg <doob me.com> wrote:

 On 2011-07-04 16:31, Jonathan Sternberg wrote:
 glut has the function:

      void glutInit( int* pargc, char** argv );

 In order to use it. Since D has an ABI compatible with C, I should be  
 able to
 write a D file with extern (C) on the glut functions. How would I wrap  
 this
 function to be used with D arrays? Such as:

 int main(string[] args)
 {
      glutInit( /* I don't know what to do here */ );
      return 0;
 }

 Thanks.

It depends on what your needs are. If your not actually using the arguments then you can pass in 0 and null, or 1 and the name of the application.

A typical library that uses standardized arguments (i.e. parameters that always mean the same thing across applications that use that library) has a parameter pre-processing function such as this which "consume" their specific arguments from the command line. The idea is, you pass the command line to those functions, the library processes its specific arguments, removing them from the command line array, and then all applications using that library have a way to control the library from the command line. I think the first one I remember having this is X and Xt. For example, most X-based applications you can pass --display=mysystem:0 and it uses that display. The applications simply use a libX function that processes those args from the command line and never have to deal with it.
 As an alternative, most platforms have an API for getting the arguments  
 passed to an application.

 Mac OS X: extern (C) char*** _NSGetEnviron();
 Posix: extern (C) extern char** environ;

Those get the environment variables, not the command line arguments.
 Don't know about Windows.

Windows actually does have a command line fetching function. Can't remember what it is, but if I had to guess I'd say it was GetCommandLine :) -Steve
Jul 04 2011
parent Jacob Carlborg <doob me.com> writes:
On 2011-07-04 18:59, Steven Schveighoffer wrote:
 On Mon, 04 Jul 2011 12:51:48 -0400, Jacob Carlborg <doob me.com> wrote:

 On 2011-07-04 16:31, Jonathan Sternberg wrote:
 glut has the function:

 void glutInit( int* pargc, char** argv );

 In order to use it. Since D has an ABI compatible with C, I should be
 able to
 write a D file with extern (C) on the glut functions. How would I
 wrap this
 function to be used with D arrays? Such as:

 int main(string[] args)
 {
 glutInit( /* I don't know what to do here */ );
 return 0;
 }

 Thanks.

It depends on what your needs are. If your not actually using the arguments then you can pass in 0 and null, or 1 and the name of the application.

A typical library that uses standardized arguments (i.e. parameters that always mean the same thing across applications that use that library) has a parameter pre-processing function such as this which "consume" their specific arguments from the command line. The idea is, you pass the command line to those functions, the library processes its specific arguments, removing them from the command line array, and then all applications using that library have a way to control the library from the command line. I think the first one I remember having this is X and Xt. For example, most X-based applications you can pass --display=mysystem:0 and it uses that display. The applications simply use a libX function that processes those args from the command line and never have to deal with it.
 As an alternative, most platforms have an API for getting the
 arguments passed to an application.

 Mac OS X: extern (C) char*** _NSGetEnviron();
 Posix: extern (C) extern char** environ;

Those get the environment variables, not the command line arguments.

Hehe. Wonder what I was thinking. Anyway, the platforms usually do have an API for that, second try: Mac OS X: extern(C) char*** _NSGetArgv(); extern(C) int* _NSGetArgc(); Linux: I read somewhere you could read from /proc/<pid>/cmdline Where <pid> is the process id.
 Don't know about Windows.

Windows actually does have a command line fetching function. Can't remember what it is, but if I had to guess I'd say it was GetCommandLine :) -Steve

Seems to be that one. -- /Jacob Carlborg
Jul 04 2011
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 05 Jul 2011 00:29:14 -0400, Jonathan Sternberg  
<jonathansternberg gmail.com> wrote:

 It's one of the applications that consumes command line arguments. So if  
 I wanted
 to implement this, a copy of the D strings (and null terminated) would  
 have to be
 made. I would also likely need to add another slot to the command line  
 arguments
 as usually the command line is null terminated for C programs.

 Generally, command line arguments don't modify the parameters. But C  
 isn't
 particularly good at using const correctness.

 A wrapper around glutInit would require copying the array to a C-style  
 array,
 calling the extern (C)'d function, then copying back the changes to the  
 D side
 back to a D style array. Right?

Yes, probably the best thing to do. -Steve
Jul 05 2011