- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我希望调用第 3 方库函数,它接受 const char* const*
作为参数类型:-
class Arguments
{
public:
Arguments(int argc, const char* const* p_argv = 0);
private:
deque<std::string> m_Args;
}
在库实现中,传递的对象通常是指向 char** argv
第一个元素的(const)指针。然后将字符串缓存在私有(private)成员变量 (m_Args
) 中,所以我认为 p_argv
中的指针只需要在持续时间内有效的 build 。
主要问题:我怎样才能或应该创建那个 const char* const* p_argv
变量?
更多解释
我正在尝试传递从其他数组类型(Boost Python list
和 tuple
)转换而来的对象,并试图找到一个安全的 ( RAII )这样做的方法。
我将在我的代码中的许多不同地方执行此操作,因此我尝试实现可以为我执行类型转换的可重用函数。例如
// File : converter.hpp
///! ConvertPyListToCharArrayPointer
///
/// Convert a Python list to const char* const*.
/// \param list - Python list of strings to convert. [in]
/// \param pargv - array of const char pointers. [in/out]
/// \returns - const pointer to first element in const char* array.
const char* const* ConvertPyListToCharArrayPointer(
const boost::python::list& list, const char** pargv);
我希望 pargv
可以在堆栈上创建,从一个函数然后调用 ConvertPyListToCharArrayPointer
和 store_arguments
。但是,代码的单元测试表明,当从 Arguments
类恢复时,存储的字符串变得无效。 (这是有道理的;我为指针数组分配了存储空间,但没有为这些指针指向的字符串分配存储空间)。
转换器实现
原始的 ConvertPyListToCharArrayPointer
实现是:-
在堆栈上
// File : converter.cpp
const char* const* ConvertPyListToCharArrayPointer(
const boost::python::list& list, const char** pargv)
{
boost::python::stl_input_iterator<std::string> cur_key(list), end;
std::string temp_s;
int i=0;
while (cur_key != end)
{
// Get current arg as std::string
temp_s = (*cur_key++);
// Save string as a const char*, in pargv[i]
pargv[i++] = temp_s.c_str();
}
pargv[i] = NULL;
// Validation code...
const char* const* m_argv = &pargv[0];
return m_argv;
}
为了准确了解发生了什么,我部署了一大堆打印语句。它说 Validation code...
,我目前有:-
printf("returning address (pargv[0]) of %s (%p)\n", pargv[0], &pargv[0]);
printf("pargv[1] of %s (%p)\n", pargv[1], &pargv[1]);
printf("pargv[2] of %s (%p)\n", pargv[2], &pargv[2]);
printf("pargv[3] of %s (%p)\n", pargv[3], &pargv[3]);
if (&pargv[0] == &pargv[1])
printf("addresses of pargv[0] and [1] are the same\n");
通过上面的 ConvertPyList...
实现,给定 Python 列表 ["foo", "bar", "baz"]
,这些打印语句显示:-
returning address (pargv[0]) of baz (0x7fffffffa410)
pargv[1] of bar (0x7fffffffa418)
pargv[2] of baz (0x7fffffffa420)
pargv[3] of (null) (0x7fffffffa428)
它显然应该显示 foo
、bar
、baz
,而它显示的是 baz
、 bar
, baz
.
让它工作 - malloc
并复制字符串
我能够让 foo
、bar
和 baz
达成一致的唯一方法是调用 malloc
为存储在 pargv
中的每个 char*
:-
const char* const* pyblast::ConvertPyListToCharArrayPointer(
int argc, const boost::python::list& list, const char** pargv)
{
int i=0;
boost::python::stl_input_iterator<std::string> cur_key(list), end;
char* cur_ptr;
while (cur_key != end)
{
// Allocate memory on heap.
cur_ptr = (char*) malloc( strlen( (*cur_key).c_str() ) );
// Copy string into malloc'd memory
if (cur_ptr)
strcpy(cur_ptr, (*cur_key).c_str());
else
fprintf(stderr, "malloc failure!\n");
// Save pointer.
pargv[i++] = cur_ptr;
++cur_key;
}
pargv[i] = NULL;
// Validation code...
const char* const* m_argv = &pargv[0];
return m_argv;
}
但是现在我有一大堆重复的字符串,我需要在调用代码中释放它们。是否有更安全的 RAII 类方法来创建此 const char* const*
数组?
也许有一种标准类型的指针(在 STL 或 Boost 中)可以在这里使用。使用 boost::make_shared
似乎没有成功...
单元测试代码
如果您希望自己编译或测试代码,以下内容应该有所帮助:-
我创建了以下 C++ 测试文件:-
/// File: test_converters.cpp
#include "converter.hpp"
// Easiest just to include the source whilst testing...
#include "converter.cpp"
#include <boost/python/def.hpp>
#include <boost/python/list.hpp>
#include <boost/python/module.hpp>
// Create and return the Python list: ["foo", "bar", "baz"]
boost::python::list make_dummy_list(void)
{
boost::python::list dummy_list = boost::python::list();
dummy_list.append("foo");
dummy_list.append("bar");
dummy_list.append("baz");
return dummy_list;
}
int TestPyListConverter(void)
{
// Create data to be tested.
boost::python::list py_argv = make_dummy_list();
ssize_t argc = boost::python::len(py_argv);
const char* pargv[argc+1]; //< pointer array
const char* const* m_pargv = //< type we're converting to / testing.
pyblast::ConvertPyListToCharArrayPointer(argc, py_argv, pargv);
// Free pargv, if necessary...
/// Tests, from Python perspective:-
ssize_t i = 0; // current index on m_pargv
char* p_argv; // temporary pointer
while (m_pargv[i] != NULL && i <= argc)
{
p_argv = PyString_AsString(PyList_GetItem(argv.ptr(), i) );
if( strcmp(m_pargv[i++], p_argv) != 0)
{
PyErr_SetString(PyExc_Exception,
"Test failed. m_pargv[i] != p_argv.");
boost::python::throw_error_already_set();
}
if (i > 4) // didn't find NULL pointer at end of array.
return 1;
}
return 0;
}
BOOST_PYTHON_MODULE(test_converter)
{
boost::python::def("test_py_list_converter", &TestPyListConverter);
}
注意虽然这在使用 malloc
时有效,但在我看来它像内存泄漏代码,因为 pargv 中的指针不是free
。理想情况下,调用代码不需要担心这个......
这可以用命令编译:
$ gcc -O1 -shared -g -pipe -fstack-protector -fPIC -I/usr/include/python2.7 -I./ ./test_converters.cpp -o ./test_converter.so -lboost_python -lpython2.7
并执行:
$ python -c 'import test_converter; test_converter.test_py_list_converter()'
最佳答案
如果您的主要问题是,如何将队列转换为 const char* const * ,那么:有时会使用指向某物的指针来指向某物数组的第一个元素。因此,在 const char* const * 的情况下,可能意味着指向数组第一个元素的指针以及指向 char 数组的指针。对于每个数组,必须有某种协议(protocol)来表示数组的长度。在 const char* 的情况下,这可能是一个 C 字符串,通常以 0 结尾。对于指向 char 的指针的数组,0 也可用于指示数组的结尾。回到你的问题:
您可以使用 std::vector 并使用 std::string.c_str() 为队列的所有元素返回的值对其进行初始化。向 vector 添加最后一个 0 指针。现在您可以将 vector 的第一个元素的地址转换为 const char* const *。
不是,只要指针 vector 和字符串队列有效,您获得的指针才有效。
std::deque< std::string > input;
std::vector< const char* > v;
for ( std::deque< std::string >::const_iterator i = input.begin(); i != input.end(); ++i )
v.push_back( i->c_str() );
v.push_back( 0 );
const char* const * p = &v[ 0 ];
关于c++ - 创建一个 const char* const* 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15946449/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!