getopt_long_only return -1 第二次调用

getopt_long_only return -1 on second call

我正在为接受参数的过程编写 C++ 到 tcl 的转换。它使用 getop_long_only。我第一次能够加载创建的共享库和 运行。然而,我第二次调用时,getop_long_only 总是给我 -1,这导致 proc 出现故障。调用快照如下。我还包括代码部分。你能帮忙解释一下是怎么回事吗?

********************* 呼叫 ************************ ****

enter code here
$ tclsh
% load area.so area
% area --area --length 4.0 --breadth 4.0
OPT ==> 97
OPT ==> 108
OPT ==> 98
OPT ==> -1
Area0: 1
Perimeter0: 0
Length0: 4
Breadth0: 4

Area: 16
Area: 16
Perimeter: 0

% area --area --length 4.0 --breadth 5.0
OPT ==> -1
rea0: 0
Perimeter0: 0
Length0: -1
Breadth0: -1

-area:           Return the area
-perimeter:      Return the perimeter
-length <val>:   Specify the length
-breadth <val>:  Specify the width
-help:           Show help
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <iostream>
#include <tcl.h>

//  Program to calculate the area and perimeter of 
//  a rectangle using command line arguments
//----------------------------------------------------
void PrintHelp() {
   std::cout <<
        "-area:           Return the area\n"
        "-perimeter:      Return the perimeter\n"
        "-length <val>:   Specify the length\n"
        "-breadth <val>:  Specify the width\n"
        "-help:           Show help\n";
   exit(1);
}


//  area --
//  This implements the random Tcl command. With no arguments
//  the command returns a random integer.
//  With an integer valued argument "range",
//  it returns a random integer between 0 and range.
//--------------------------------------------------------------
extern "C" int AreaCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char **argv) {
   int opt= 0;
   int area = 0, perimeter = 0, breadth = -1, length =-1;

   while (1) {

  //Specifying the expected options
  //The two options l and b expect numbers as argument
     static struct option long_options[] = {
        {"area",      no_argument,       0,  'a' },
        {"perimeter", no_argument,       0,  'p' },
        {"length",    required_argument, 0,  'l' },
        {"breadth",   required_argument, 0,  'b' },
        {"help",      no_argument,       0,  'h' },
        {0,           0,                 0,  0   }
     };

     int long_index =0;
     char* const* new_argv = const_cast<char * const *>(argv);
     opt = getopt_long_only(argc, new_argv,"", long_options, &long_index );

     printf("OPT ==> %d\n",opt);

     if (opt == -1) {
        break;
     }

     switch (opt) {
        case 'a' : area = 1;
        break;
        case 'p' : perimeter = 1;
        break;
        case 'l' : length = atoi(optarg);
        break;
        case 'b' : breadth = atoi(optarg);
        break;
        case 'h': // -h or --help
        case '?': // Unrecognized option
        default: PrintHelp();
        exit(EXIT_FAILURE);
     }
  }

  printf("Area0: %d\n",area);
  printf("Perimeter0: %d\n",perimeter);
  printf("Length0: %d\n",length);
  printf("Breadth0: %d\n\n",breadth);

  if (length == -1 || breadth ==-1) {
     PrintHelp();
     exit(EXIT_FAILURE);
  }
  // Calculate the area
  if (area == 1) {
     area = length * breadth;
     printf("Area: %d\n",area);
  }

  // Calculate the perimeter
  if (perimeter == 1) {
     perimeter = 2 * (length + breadth);
     printf("Perimeter: %d\n",perimeter);
  }

  //char* result;
  //sprintf(result,"%d",rand);
  //Tcl_SetResult(interp, result, TCL_VOLATILE);

  printf("Area: %d\n",area);
  printf("Perimeter: %d\n",perimeter);

  return TCL_OK;

 }

如果我们查看 documentation for getopt_long_only(),我们会看到这些关键行:

The variable optind is the index of the next element to be processed in argv. The system initializes this value to 1. The caller can reset it to 1 to restart scanning of the same argv, or when scanning a new argument vector.

还有:

Notes

A program that scans multiple argument vectors, or rescans the same vector more than once, and wants to make use of GNU extensions such as '+' and '-' at the start of optstring, or changes the value of POSIXLY_CORRECT between scans, must reinitialize getopt() by resetting optind to 0, rather than the traditional value of 1. (Resetting to 0 forces the invocation of an internal initialization routine that rechecks POSIXLY_CORRECT and checks for GNU extensions in optstring.)

你的代码在解析一组新的参数之前不会重置 optind(不是 getopt() 和朋友通常提到的东西,因为他们的正常情况是一次性的解析命令行参数)。对于这种情况,您应该更改它。如果你打算从多个线程使用你的扩展,你应该切换到一个不同的解析解决方案,它更多地使用 Tcl 的内置函数;他们没有在线程之间共享状态。