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

C++ 命令行参数的第二个参数的格式不是char**argv或char*argv[],c++,segmentation-fault,command-line-arguments,argv,C++,Segmentation Fault,Command Line Arguments,Argv,为了解决我的问题,我想知道是否/如何以char**argv或char*argv[]以外的格式定义命令行参数的第二个变量。pybind11不允许在函数的输入中使用这两种方法。以下是我尝试过的方法: 方法1: 方法3: 这适用于Ubuntu minimal和g++7.4.0,以及Windows 10 Visual Studio 2019编译器。但是,它不使用clang编译。正如其他人指出的那样,这不是一种解决办法,也是一种非常糟糕的做法。它可能导致未定义的行为,具体取决于编译器、操作系统和内存的当前

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

方法1: 方法3:
这适用于Ubuntu minimal和
g++7.4.0
,以及Windows 10 Visual Studio 2019编译器。但是,它不使用
clang
编译。正如其他人指出的那样,这不是一种解决办法,也是一种非常糟糕的做法。它可能导致未定义的行为,具体取决于编译器、操作系统和内存的当前状态。这不应该在任何实际代码中使用。任何C/C++代码中的主函数的形式都必须是
main()
main(int-argc,char**argv)
,或
main(int-argc,char*argv[])

让我们一个接一个地解决在冗长讨论中出现的大量问题


问题1:为什么在使用一些非标准参数(如字符串向量或int指针)指向
main

<> >“代码> int、char *<代码>的参数类型是由C和C++标准定义的。除了非标准扩展,您不能使用其他类型

根据ISO/IEC 9899(C语言),5.1.2.2.1程序启动:

程序启动时调用的函数名为main。实现没有声明此函数的原型。应使用返回类型
int
进行定义,且无参数:

int main(void){/*…*/}

或具有两个参数(此处称为
argc
argv
,但可以使用任何名称,因为它们是声明它们的函数的本地名称):

intmain(intargc,char*argv[]){/*…*/}

或同等品;或者以其他实现定义的方式

最后一句话允许我提到的那些扩展。我知道的一个这样的扩展是GCC的
环境


问题2:我如何解决这个问题?

你没有

使用与标准或编译器扩展定义的类型不同的类型是未定义行为,这可能(但不需要)导致SEGFULTS。不要调用未定义的行为。不要“胡乱修改”标准。它不是一个“变通办法”,更不用说“解决方案”,它是一个随时可能在你面前爆发的坏代码


问题3:我如何
pybind
一个以
char**
为参数的第三方函数?

你不需要,因为这不是一场比赛


问题4:我如何通过
pybind
与这样的函数接口?

您编写了一个包装函数,该函数在前端接受
pybind
支持的参数(例如
std::vector
),对这些参数进行适当的封送,然后使用封送的参数为您调用第三方后端函数。(当然,如果需要,也可以对返回类型执行相反的操作。)

有关如何执行此操作的惯用示例,请参阅


问题5:我可以
pybind
到第三方
main


这是不明智的,因为
main
是一个特殊函数,被调用的代码可能会做出调用代码不遵守、也不能遵守的假设(如
atexit
回调)。它当然不是第三方期望作为库函数调用的函数。

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

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

int cppmain(std::string program, std::vector<std::string> args) {
    std::cout << program << " got arguments:\n";
    for(auto& arg : args) {
        std::cout << " " << arg << "\n";
    }
    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});
}
#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] << '\n';
    }
    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());
}

我很困惑。不应该调用
main
,因此这个问题对您来说没有意义me@Foad:实际上没有混合代码这回事。你在C++中编译这很明显,因为你使用C++类。@ FAAD:反正它们并不是一个最小的完整的可验证的例子,因为没有足够的代码来验证问题。使用
main
也增加了大量的混乱,如所有评论和所有答案中所述。如果
main
不是所讨论的方法,那么混淆就会消失。(ctd。)因为您根本不打算调用
main
(如您所述),所以segfault问题与您实际试图实现的目标完全无关;因此,要求一个“解决方案”是没有成效的。唯一不专业的一点是,你忽略了/没有承认你得到的答案。你不能“绕过标准”,句号。如果你愿意的话,请接受回答你的人确实知道我们在谈论什么,并且确实理解你的问题——甚至比你更好一点。谢谢你的帖子。我知道这个标准,但如果可能的话,我正在寻找一种绕过它的方法。基本上,如果我可以将输入存储为除
char*argv[]
char**argv
以外的任何类型,然后将它们转换为这些形式,那么问题应该得到解决。@Foad:有关将
argv
转换为字符串向量的快速方法,请参阅更新的答案。这真的是你能做的最好的了。@DevSolar:混乱是因为Foad正在将一个随机方法绑定到pybind,而这个问题与
main
@Foad:完全修改了答案无关。如果您的问题(和评论)的任何部分仍然没有回答,请留下一张便条。@DevSolar当然。现在有点忙。但我会研究一下,然后给你反馈。不幸的是,其他用户没有事先咨询我就编辑了我的问题,造成了这种混乱。
char*arg[]
char**argv
不能在函数的任何输入中。它们不是。输入到
cppmain
func
#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\n", argv_[i].c_str());
    }
}
#include <stdio.h>

int main(int argc, long* argv_){
    for (int i = 0; i < argc; ++i){
        printf("%s\n", (char *)(argv_[i]));
    }
}
#include <iostream>
#include <string>
#include <vector>

int cppmain(std::string program, std::vector<std::string> args) {
    std::cout << program << " got arguments:\n";
    for(auto& arg : args) {
        std::cout << " " << arg << "\n";
    }
    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});
}
#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] << '\n';
    }
    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());
}