Click here to Skip to main content
Licence LGPL3
First Posted 12 Feb 2011
Views 31,760
Downloads 3,165
Bookmarked 53 times

Full getopt Port for Unicode and Multibyte Microsoft Visual C, C++, or MFC Projects

By | 17 Feb 2012 | Article
Supports getopt, getopt_long, and getopt_long_only and POSIXLY_CORRECT environment flag

Introduction

This software was written after hours of searching for a robust Microsoft C and C++ implementation of getopt, which led to devoid results.

This software is a modification of the Free Software Foundation, Inc. getopt library for parsing command line arguments and its purpose is to provide a Microsoft Visual C friendly derivative. The source code provides functionality for both Unicode and Multibyte builds and supports getopt, getopt_long, and getopt_long_only. Additionally the code supports the POSIXLY_CORRECT environment flag. The library utilizes the standard Microsoft C TCHAR definition to toggle between char and wchar_t via the definition of the _UNICODE preprocessor directive.

The original GNU code used several header and implementation files containing numerous preprocessor directives specific to Linux environments which have been removed. After removing unneeded dependencies, it was condensed into a single header and implementation file which can be compiled into a DLL, LIB, or directly included into any Visual C, C++, or MFC project. The getopt library can be used by proprietary software, however; certain measures need to be taken to ensure proprietary code adheres to the Lesser GNU Public License for non-derivative works. Please refer to the licensing section of this article for more details on how this software is licensed.

For the sake of brevity, this article doesn't discuss how to use the getopt functions. Anyone new to using the getopt functions should refer to the GNU tutorial for using getopt.

Licensing

Since getopt is licensed under LGPL, it is free to use in proprietary software under some restrictions. When using this library as part of a proprietary software solution, it is important that the library is used as a dynamically linked library (DLL) and is not statically linked or directly compiled into proprietary source code. Static linkage requires that your software be released GPL. Therefore, by keeping the library separately referenced via Dynamic Link Library (DLL), allows the DLL to be modified and updated without changing the proprietary software which utilizes the library; under this condition proprietary software is said to "use" the library. Thus, it is not considered to be a derivative work and can be distributed freely under any license.

Preprocessor Definitions

Compiling getopt as a Dynamic Link Library (DLL) requires the preprocessor definition of EXPORTS_GETOPT. The definition of EXPORTS_GETOPT sets the internal preprocessor definition _GETOPT_API to the value __declspec(dllexport). Compiling getopt as a Static Library (LIB) or directly including the source and header file within a project requires the preprocessor definition of STATIC_GETOPT. The definition of STATIC_GETOPT clears the value of the internal preprocessor definition of _GETOPT_API. Compiling software to use getopt.dll requires that no library specific preprocessor definitions be used. When no library specific preprocessor definitions are used the value assigned to the internal preprocessor definition _GETOPT_API is __declspec(dllimport).

The code segment below demonstrates the logic outlined above:

#if defined(EXPORTS_GETOPT) && defined(STATIC_GETOPT)
    #error "The preprocessor definitions of EXPORTS_GETOPT 
        and STATIC_GETOPT can only be used individually"
#elif defined(STATIC_GETOPT)
#pragma message("Warning static builds of getopt violate the Lesser GNU Public License")
    #define _GETOPT_API
#elif defined(EXPORTS_GETOPT)
    #pragma message("Exporting getopt library")
    #define _GETOPT_API __declspec(dllexport)    
#else
    #pragma message("Importing getopt library")
    #define _GETOPT_API __declspec(dllimport)
#endif

Sample Code Provided

To help with understanding how to use the code, many versions have been provided for download. The following downloads are provided:

  • Visual Studio .NET 2010 ANSI Project
  • Visual Studio .NET 2008 ANSI Project
  • Visual Studio .NET 2008 MFC Project
  • Visual Studio .NET 2005 ANSI Project
  • Visual Studio .NET 2005 MFC Project
  • Visual Studio 6 ANSI Project
  • Visual Studio 6 MFC Project

Using the Code

The code is used identical to GNU getopt.

#include <stdio.h>
#include <stdlib.h>
#include "getopt.h"

int _tmain(int argc, TCHAR** argv)
{
    static int verbose_flag;
    int c;

    while (1)
    {        
        static struct option long_options[] =
        {
            {_T("verbose"), ARG_NONE, &verbose_flag, 1},
            {_T("brief"),   ARG_NONE, &verbose_flag, 0},
            {_T("add"),     ARG_NONE, 0, _T('a')},
            {_T("append"),  ARG_NONE, 0, _T('b')},
            {_T("delete"),  ARG_REQ,  0, _T('d')},
            {_T("create"),  ARG_REQ,  0, _T('c')},
            {_T("file"),    ARG_REQ, 0 , _T('f')},
            { ARG_NULL , ARG_NULL , ARG_NULL , ARG_NULL }
        };

        int option_index = 0;
        c = getopt_long(argc, argv, _T("abc:d:f:"), long_options, &option_index);

        // Check for end of operation or error
        if (c == -1)
            break;

        // Handle options
        switch (c)
        {
        case 0:
            /* If this option set a flag, do nothing else now. */
            if (long_options[option_index].flag != 0)
                break;
            _tprintf (_T("option %s"), long_options[option_index].name);
            if (optarg)
                _tprintf (_T(" with arg %s"), optarg);
            _tprintf (_T("\n"));
            break;

        case _T('a'):
            _tprintf(_T("option -a\n"));
            break;

        case _T('b'):
            _tprintf(_T("option -b\n"));
            break;

        case _T('c'):
            _tprintf (_T("option -c with value `%s'\n"), optarg);
            break;

        case _T('d'):
            _tprintf (_T("option -d with value `%s'\n"), optarg);
            break;

        case _T('f'):
            _tprintf (_T("option -f with value `%s'\n"), optarg);
            break;

        case '?':
            /* getopt_long already printed an error message. */
            break;

        default:
            abort();
        }
    }

    if (verbose_flag)
        _tprintf (_T("verbose flag is set\n"));


    if (optind < argc)
    {
        _tprintf (_T("non-option ARGV-elements: "));
        while (optind < argc) _tprintf (_T("%s "), argv[optind++]);
        _tprintf (_T("\n"));
    }
    return 0;
}     

Using this Code with C++ Precompiled Headers

When using this code statically within a C++ project with precompiled headers, it is necessary to rename getopt.c to getopt.cpp in order to circumvent the following compiler error:

“C1853 - Precompiled header file is from a previous version of the compiler, 
or the precompiled header is C++ and you are using it from C (or vice versa).”

Additionally precompiled header file must be added as the first include of the getopt.c or getopt.cpp file. For example, if you are using "stdafx.h" as the precompiled header, the following would be expected:

// File comments removed
#include "stdafx.h"
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
#include "getopt.h"

History

  • 02/03/2011 - Initial release
  • 02/20/2011 - Fixed L4 compiler warnings
  • 07/05/2011 - Added no_argument, required_argument, optional_argument def
  • 08/05/2011 - Fixed non-argument runtime bug which caused runtime exception
  • 08/09/2011 - Added code to export functions for DLL and LIB
  • 02/15/2012 - Fixed _GETOPT_THROW definition missing in implementation file

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)

About the Author

Ludvik Jerabek

Software Developer

United States United States

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
Question_GETOPT_THROW in getopt.c Pinmemberazder55621:09 17 Nov '11  
AnswerRe: _GETOPT_THROW in getopt.c PinmemberLudvik Jerabek17:13 18 Nov '11  
Questionhow to USE it Pinmemberericoporto11:39 24 Sep '11  
AnswerRe: how to USE it PinmemberLudvik Jerabek12:14 24 Sep '11  
QuestionJust an advisory about the licence Pinmembersgllama5:59 9 Aug '11  
AnswerRe: Just an advisory about the licence PinmemberLudvik Jerabek12:31 9 Aug '11  
GeneralMy vote of 5 PinmemberMicroImaging9:02 8 Aug '11  
GeneralRe: My vote of 5 Pinmemberseachanged12:01 26 Dec '11  
GeneralMy vote of 1 Pinmemberkouhinn20:42 26 Jul '11  
GeneralRe: My vote of 1 PinmemberLudvik Jerabek15:25 3 Aug '11  
GeneralThanks & suggestion PinmemberLu.P11:27 11 Mar '11  
GeneralRe: Thanks & suggestion PinmemberLudvik Jerabek14:53 12 Mar '11  
GeneralRe: Thanks & suggestion PinmemberLu.P6:16 13 Mar '11  
GeneralMy vote of 5 PinmemberMember 16579820:48 21 Feb '11  
GeneralVery nice! PinmentorHans Dietrich8:09 19 Feb '11  
GeneralRe: Very nice! PinmemberLudvik Jerabek13:23 19 Feb '11  
GeneralRe: Very nice! PinmemberLudvik Jerabek11:52 20 Feb '11  
GeneralMy vote of 5 PinmemberSharjith3:59 14 Feb '11  
GeneralRe: My vote of 5 PinmemberLudvik Jerabek5:07 14 Feb '11  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web02 | 2.5.120517.1 | Last Updated 17 Feb 2012
Article Copyright 2011 by Ludvik Jerabek
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid