我有这个C风格的初始化代码:
const char * const vlc_args[] =
{
"-I", "dummy",
"--ignore-config",
"--extraintf=logger",
"--verbose=2"
"--plugin-path=/usr/lib/vlc"
};
//tricky calculation of the char space used
libvlc_new(sizeof(vlc_args)/sizeof(vlc_args[0]), vlc_args, &exc);
由于我需要动态--plugin-path
参数,我不能再使用静态数组了。所以我提出了一个C ++替代方案:
std::string pluginpath = "test";
libvlc_exception_t exc;
std::vector<std::string> args;
args.push_back("-I");
args.push_back("dummy");
args.push_back("--ignore-config");
args.push_back("--extraintf=logger");
args.push_back("--verbose=2");
args.push_back("--ipv4");
args.push_back("--plugin-path=" + pluginpath);
std::string combinedString;
for (size_t idx = 0; idx < args.size(); ++idx)
{
combinedString.append(args[idx]);
combinedString.resize(combinedString.size() + 1);
combinedString[combinedString.size() - 1] = 0;
}
combinedString.resize(combinedString.size() + 1);
combinedString[combinedString.size() - 1] = 0;
size_t size = combinedString.size();
const char * data = combinedString.c_str();
libvlc_new(size, &data, &exc); // => error occurs here (not at end of scope or anything)
但是这会导致分段错误。所以我的代码中一定有错误,我似乎无法找到。有人能发现它吗?
解决!
感谢Joseph Grahn和Jason Orendorff。我对C风格数组内存布局的想法是错误的。我认为所有数据都被组织成一个大的顺序块。实际上,它是指向每个单独字符串的第一个字符的指针列表。
此代码有效:
std::vector<const char*> charArgs;
for (size_t idx = 0; idx < args.size(); ++idx)
{
charArgs.push_back(&(args[idx][0]));
}
mVLCInstance = libvlc_new(charArgs.size(),
&charArgs[0],
&mVLCException);
答案 0 :(得分:4)
您将所有参数附加到单个字符串中,然后将指向const char *字符串的指针传递给libvlc_new,就好像它是一个char *数组。
(我不确定这是不是问题,但似乎有点奇怪。)
答案 1 :(得分:4)
我认为Josef Grahn是对的:API需要一个实际的指针数组。
如果您不需要以编程方式添加参数,则可以返回使用数组:
std::string pluginpath = "test";
std::string pluginpath_arg = "--plugin-path=" + pluginpath;
const char *args[] = {
"-I", dummy, "--ignore-config", ..., pluginpath_arg.c_str()
};
libvlc_exception_t exc;
libvlc_new(sizeof(args) / sizeof(args[0]), args, &exc);
编辑:在这里使用c_str()
可能 也有问题。如果VLC保留指针并稍后再次使用它,则为真;我不知道文档是否属于这种情况。
答案 2 :(得分:1)
没有解决方案,因为可能会有更多问题
您只发送1个字符串。(不确定libvlc_new
是否允许)所以第一个参数应设置为1,即size = 1
。我相信这将解决分割问题。但我怀疑libvlc_new
只能用一行多个参数调用。
在原始代码sizeof(vlc_args)/sizeof(vlc_args[0])
中,参数的数量将作为向量中的条目。在你的例子中等于6。
您的代码
size_t size = combinedString.size(); // a long string, size >> 1
const char * data = combinedString.c_str(); // data is a pointer to the string
libvlc_new(size, &data, &exc);
// size should be 1 because data is like an array with only one string.
// &data is the adress to the "array" so to speak. If size > 1 the function
// will try to read pass the only string available in this "array"
我认为Jason Orendorff有一个很好的解决方案来解决这个问题......
答案 3 :(得分:1)
库调用需要一个指向const char*
数组的指针(这是几个指针),但是你传递一个指针。将更多字符附加到该字符串的末尾并不重要。
要动态构建所需指针的数组,您可以使用另一个vector
:
// store c_str() pointers in vector
std::vector<const char*> combined;
for (size_t idx = 0; idx < args.size(); ++idx) {
combined.push_back(args[idx].c_str());
}
// pass pointer to begin of array (it is guaranteed that the contents of a vector
// are stored in a continuous memory area)
libvlc_new(combined.size(), &(combined[0]), &exc);
Jason Orendorff的注释在这里也是有效的:如果libvlc_new
将传递的指针存储在内部供以后使用,这将不起作用。
答案 4 :(得分:1)
你试过了吗?
libvlc_new(size, data, &exc);
而不是
libvlc_new(size, &data, &exc);
似乎你使用空字节使字符串像一个字符数组一样,但是你将指针传递给char *“array”而不仅仅是数组。
答案 5 :(得分:0)
我有同样的问题;我想动态生成参数,但是以安全的c ++方式。
我遇到的解决方案是使用unique_ptr&lt; []&gt; C ++ 11新手。例如:
unique_ptr<char *[]> vlc_argv;
int vlc_argc;
...
auto vlc(libvlc_new(vlc_argc, vlc_argv.get()));
这给了我一个很好的RAII对象来保存我的参数,因为我仍然可以传递给libvlc_new()。由于参数是argv中的原始指针,由操作系统管理,我们可以直接在vlc_argv中使用它们。
作为另一个例子,假设我处理argv
中的前几个args(在&#34; ...&#34;上面的某个区域),并想要传递来自{{1}的所有内容}到libvlc_new():
next_arg
答案 6 :(得分:-1)
问题是由于使用c_str()并存储指针。
请参阅stringstream, string, and char* conversion confusion
编辑忘了我说的......已经晚了...看到评论:)