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());
}