在Mac上用汉字命令调用popen()
Call popen() on a command with Chinese characters on Mac
我正试图在Mac上使用popen()命令在文件上执行程序。为此,我创建了一个形式为<path-to_executable> <path-to-file>
的命令,然后对该命令调用popen()。现在,这两个组件都是用char*声明的。我需要读取命令的输出,所以我需要popen()给出的管道。
现在,文件的路径可以包含中文、日语、俄语和几乎任何其他字符。为此,我可以将文件的路径表示为wchar_t*。但这对popen()不起作用,因为显然Mac/Linux不像Windows那样有一个宽的_wpopen(。
我还有其他方法可以做到这一点吗?我从一个只能给我wchar_t*的数据结构中获取文件的路径,所以我必须从那里获取它,并在需要时进行适当的转换。
提前谢谢。
编辑:
似乎有一天你会把头发拔出来。
因此,我尝试使用wcstomb,但对"C.UTF-8"及其任何排列的setlocale调用都失败了。不出所料,wcstobbs调用失败,之后返回-1。
然后,我尝试根据在谷歌上搜索的一些示例代码编写自己的iconv实现。我想出了一个顽固地拒绝工作的办法:
iconv_t cd = iconv_open("UTF-8", "WCHAR_T");
// error checking here
wchar_t* inbuf = ...; // get wchar_t* here
char outbuf[<size-of-inbuf>*4+1];
size_t inlen = <size-of-inbuf>;
size_t outlen = <size-of-inbuf>*4+1;
char* c_inbuf = (char*) inbuf;
char* c_outbuf = outbuf;
int ret = iconv(cd, &c_inbuf, &inlen, &c_outbuf, &outlen);
// more error checking here
iconv总是返回-1,并且errno设置为EINVAL。我已验证<size-of-len>
设置正确。我不知道为什么这个代码现在失败了。
编辑2:
iconv失败了,因为我没有正确设置输入缓冲区长度。此外,Mac似乎不支持"WCHAR_t"编码,所以我将其更改为UTF-16。现在我已经更正了长度并更改了编码,但iconv只是返回,没有转换任何字符。它只返回0。
为了调试这个问题,我甚至将输入字符串更改为临时字符串,并适当地设置输入长度。即使这个iconv调用也只返回0。我的代码现在看起来像:
iconv_t cd = iconv_open("UTF-8", "UTF-16");
// error checking here
wchar_t* inbuf = ...; // get wchar_t* here - guaranteed to be UTF-16
char outbuf[<size-of-inbuf>*4+1];
size_t inlen = <size-of-inbuf>;
size_t outlen = <size-of-inbuf>*4+1;
char* c_inbuf = "abc"; // (char*) inbuf;
inlen = 4;
char* c_outbuf = outbuf;
int ret = iconv(cd, &c_inbuf, &inlen, &c_outbuf, &outlen);
// more error checking here
我已经确认转换器描述符被正确打开。from编码正确。输入缓冲区包含一些简单的字符。所有内容都是硬编码的,并且是静态的,iconv不转换任何字符,只返回0,而outbuf保持为空。
健康损失警报
popen
需要一个UTF-8字符串。为此,可以使用iconv
在不同编码之间进行转换,包括从本地wchar_t
编码转换为UTF-8。(请注意,在我的Mac OS安装中,wchar_t
实际上是32位,而不是16位。)
EDIT下面是一个在OS X Lion上运行的示例。我在使用wchar_t
编码时没有遇到问题(iconv
手册页中记录了这一点)。
#include <sys/param.h>
#include <string.h>
#include <iconv.h>
#include <stdio.h>
#include <errno.h>
char* utf8path(const wchar_t* wchar, size_t utf32_bytes)
{
char result_buffer[MAXPATHLEN];
iconv_t converter = iconv_open("UTF-8", "wchar_t");
char* result = result_buffer;
char* input = (char*)wchar;
size_t output_available_size = sizeof result_buffer;
size_t input_available_size = utf32_bytes;
size_t result_code = iconv(converter, &input, &input_available_size, &result, &output_available_size);
if (result_code == -1)
{
perror("iconv");
return NULL;
}
iconv_close(converter);
return strdup(result_buffer);
}
int main()
{
wchar_t hello_world[] = L"/éè/path/to/hello/world.txt";
char* utf8 = utf8path(hello_world, sizeof hello_world);
printf("%sn", utf8);
free(utf8);
return 0;
}
utf8_hello_world
函数接受字节长度的wchar_t
字符串,并返回等效的UTF-8字符串。如果处理指向wchar_t
的指针而不是指向wchar_t
的数组,则需要使用(wcslen(ptr) + 1) * sizeof(wchar_t)
而不是sizeof
。
Mac OS X使用UTF-8,因此需要将宽字符串转换为UTF-8。您可以使用wcstombs
来完成此操作,前提是您首先切换到UTF-8区域设置。例如:
// Do this once at program startup
setlocale(LC_ALL, "en_US.UTF-8");
...
// Error checking omitted for expository purposes
wchar_t *wideFilename = ...; // This comes from wherever
char filename[256]; // Make sure this buffer is big enough!
wcstombs(filename, wideFilename, sizeof(filename));
// Construct popen command using the UTF-8 filename
如果您不想更改程序的区域设置,也可以使用libiconv为您进行UTF-16到UTF-8的转换;您也可以推出自己的实现,因为转换并不那么复杂。
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- C++为什么尽管我调用了void函数,它却不起作用
- 构造函数正在调用一个使用当前类类型的函数
- 变量没有改变?通过向量的函数调用
- 没有为自己的结构调用列表推回方法
- bash脚本在使用popen()时不返回代码以调用C ++程序
- 在c++中使用popen调用cli实用程序时崩溃.适用于shell或fork、exec等
- 将系统和 POPEN 调用替换为不克隆进程内存的调用
- 在Mac上用汉字命令调用popen()
- 在Windows上确定从调用popen的PID