从C中的函数返回char数组的首选方式
Preferred way of returning a char array from a function in C
我目前正在处理一个C++dll,它向调用方返回一个字符串。为了使dll独立于构建过程的其余部分,以及C++缺乏标准ABI,我被迫用C字符指针包装字符串。
据我记忆所及,有两种以纯C方式返回字符串的可能性:
//Method 1
bool Foo1(wchar_t* s1, int len)
{
//Needs space for 6 chars + null terminator
if (len < 7)
return false;
wcscpy(s1, L"Hello1");
return true;
}
//Method 2
wchar_t* Foo2()
{
wchar_t* s2 = new wchar_t[10];
wcscpy(s2, L"Hello2");
return s2;
}
//Caller
int _tmain(int argc, _TCHAR* argv[])
{
wchar_t s1[10];
bool res = Foo1(s1, sizeof(s1) / sizeof(WCHAR));
wchar_t* s2 = Foo2();
delete s2;
return 0;
}
是否存在有利于这两种解决方案之一的指导方针?我看到方法1主要用于Windows API,可能是由于历史原因。然而,我也没有看到使用第二种方法有任何负面影响,它消除了调用方预先分配内存的需要。唯一的缺点是,释放分配的内存的责任现在掌握在调用者手中。谢谢你的建议。
您不希望在DLL中new
字符串,而只是返回它们。您还需要提供一个解除分配函数,调用方可以使用该函数来解除分配。因为如果调用方的delete[]
实现与DLL的new[]
实现匹配,那么根本不需要降到C级别,只需使用std::string
即可。
正如您所指出的,另一种选择是让调用者提供一个缓冲区。
第三种选择是让调用者提供分配机制。
第四种选择是使用Windows专用的分配机制来执行此任务,即BSTR
字符串、SysAllocString
和好友。
如果有必要的话,我会把它做成COM服务器,而不是纯C风格的DLL。不过,用g++做这件事很麻烦。所以,如果我也必须支持g++,我可能会做一个纯的C DLL,并使用上面提到的BSTR
。
顺便说一句,没有理由使用Microsoft;除了核心遗留代码之外,还有过时和非标准的_tmain
和_TCHAR
。由于Windows 9x的兼容性较弱,这种宏内容在2000年随着Layer for Unicode的推出而被淘汰。所以它已经过时15年了。
第三种方法:
inline char* calloc_buffer(void*,unsigned n){ return (char*)calloc(1,n);}
char* get( char*(*make_buff)(void*,unsigned n), void* );
它包括一个回调,让调用方分配缓冲区,以及一个调用方可以传递的函数,让他们调用缓冲区。这可以最大限度地提高效率。如果愿意,他们也可以使用本地缓冲区,如果不够大,可以在calloc
上回退。带有偏移量和长度的版本也很有用。
接下来,对于一个高质量的C++可移植dll,我们包括可选的仅头部包装器:
inline char* from_vector(void*v_,unsigned n){
auto v =static_cast<std::vector<char>*>(v_);
v->resize(n);
return v->data();
}
inline std::vector<char> get(){
std::vector<char> buf;
get( from_vector, &buf );
return buf;
}
它为您提供了具有近似最优C代码的近似最优C++。
这取决于情况。第二种情况会使返回错误条件变得更加困难,您可能需要考虑这一点。当然,您可以使用errno来克服这个问题。最重要的是,没有对错之分,这是与您正在使用的代码风格或您的个人偏好相匹配的,如果是您自己的应用程序。
- 如何以优化的方式同时迭代两个间距不相等的数组
- 在数组中输入 n 个整数的列表,并以类似于钟摆来回移动的方式排列它们. 输入-1 3 2 5 4,输出5 3 1 2 4
- 在C++中,建议通过数组循环的方式是什么?
- 以这种方式初始化的 char 数组是否会自动添加空终止符?
- C++通过别名指针以静默方式将错误的类型分配给数组元素
- 如何以这种方式处理字符串数组
- 数组数据以错误的方式遍历 Python/Matlab
- 使用分而治之的最大总和子数组,为什么要以不同的方式使用 for 循环,答案是错误的?
- 使用字节数组具有单字节对齐方式的结构是否安全
- 有没有一种递归的方式来制作这个字符串数组?
- 以类似数组的方式访问结构成员:在与数组不同的结构中填充?
- C 结构具有CHAR数组以不寻常的方式初始化为零
- 动态规划 - 在数组中查找目标求和方式
- 我可以以某种方式使我的矢量/数组动态更改装置数量吗?
- 一维数组映射方式的性能差异问题
- 在动态 2-D 数组中填充 0 的更简洁的方式C++
- 我需要以尺寸方式计算数组的平均值
- 如何以递归方式反转任何数组?(不使用C++标准库)
- 在编译时以增量方式创建数组
- 为什么在指针和数组的情况下,字符数组的处理方式不同