命令行参数的第二个参数,格式不是 char** argv 或 char* argv[]

为了解决我的问题这里,我想知道是否/如何定义命令行的第二个变量char** argvchar* argv[] 格式的参数.原因是 pybind11 不允许函数的输入.以下是我尝试过的方法:

To solve my problem here, I want to know if/how I can define the second variable of the command line arguments in a format other than char** argv or char* argv[]. The reason is that pybind11 doesn't allow either of those in the inputs of a function. Here are the methods I have tried:

#include <stdio.h>

int main(int argc, int* argv_){
    for (int i = 0; i < argc; ++i){
        printf("%s
", (char *)(argv_[i]));
    }
}

这种方法背后的基本原理是指针本质上是一个整数,通过将地址转换为 char 指针,应该能够获取字符串.提前感谢您的支持.

The rationale behind this method is that a pointer is intrinsically an integer and by casting the address to a char pointer, one should be able to get the strings. Thanks for your kind support in advance.

#include <stdio.h>
#include <string>

int main(int argc, std::string* argv_){
    for (int i = 0; i < argc; ++i){
        printf("%s
", argv_[i].c_str());
    }
}

方法三:

#include <stdio.h>
#include <string>
#include <vector>

int main(int argc, std::vector<std::string> argv_){
    for (int i = 0; i < argc; ++i){
        const char* argv__ = argv_[i].c_str();
        printf("%s
", argv_[i].c_str());
    }
}

问题:

不幸的是,上述所有方法都会导致臭名昭著的分段错误.

如果您能帮助我了解问题所在(即内存泄漏在哪里)以及如何解决问题,我将不胜感激.

I would appreciate it if you could help me know what is the problem (i.e., where is the memory leak) and how to solve them.

在评论中,有人告诉我,如果有任何其他形式,而不是 main()main(int argc, char** argv)>main(int argc, char* argv[]) 使用,难免会导致segmentation fault.但是,下面的代码有效:

In the comments I'm being told that if any other form rather than main(), main(int argc, char** argv), or main(int argc, char* argv[]) is used, it will unavoidably lead to segmentation fault. However, the code below works:

#include <stdio.h>

int main(int argc, long* argv_){
    for (int i = 0; i < argc; ++i){
        printf("%s
", (char *)(argv_[i]));
    }
}

这适用于 Ubuntu 最小和 g++ 7.4.0 以及 Windows 10 Visual Studio 2019 编译器.但是,它不能用 clang 编译.正如其他人指出的那样,这不是一个解决方案,也是一种非常糟糕的做法.根据编译器、操作系统和内存的当前状态,它可能会导致未定义的行为.这不应该在任何实际代码中使用.任何 C/C++ 代码中的 main 函数必须是 main()main(int argc, char** argv)main(intargc, char* argv[]).

This works on an Ubuntu minimal and g++ 7.4.0, and Windows 10 Visual Studio 2019 compilers. However, it does not compile with clang. As others have pointed out this is not a solution and a very bad practice. It can cause undefined behavior depending on the compiler, operating system and the current state of the memory. This should not be used in any actual code ever. The main function in any C/C++ code must be of the forms main(), main(int argc, char** argv), or main(int argc, char* argv[]).

推荐答案

看起来它毕竟不需要 main,所以你可以这样做:

It doesn't look like it needs to be main after all, so you could do like this:

#include <iostream>
#include <string>
#include <vector>

int cppmain(std::string program, std::vector<std::string> args) {
    std::cout << program << " got arguments:
";
    for(auto& arg : args) {
        std::cout << " " << arg << "
";
    }
    return 0;
}

int main(int argc, char* argv[]) {
    // create a string from the program name and a vector of strings from the arguments
    return cppmain(argv[0], {argv + 1, argv + argc});
}

<小时>

如果您需要调用封闭源代码的类似 main 函数(您无法更改),请创建一个您可以 pybind 到的包装函数,并让该函数调用封闭源代码函数.


In case you need to call a closed source main-like function (that you can not change), create a wrapper function that you can pybind to and let that function call the closed source function.

#include <cstddef>
#include <iostream>
#include <string>
#include <vector>

int closed_source_function(int argc, char* argv[]) {
    for(int i = 0; i < argc; ++i) {
        std::cout << argv[i] << '
';
    }
    return 0;
}

int pybind_to_this(std::vector<std::string> args) {
    // create a char*[]
    std::vector<char*> argv(args.size() + 1);

    // make the pointers point to the C strings in the std::strings in the
    // std::vector
    for(size_t i = 0; i < args.size(); ++i) {
        argv[i] = args[i].data();
    }

    // add a terminating nullptr (main wants that, so perhaps the closed source
    // function wants it too)
    argv[args.size()] = nullptr;

    // call the closed source function
    return closed_source_function(static_cast<int>(args.size()), argv.data());
}

相关文章