课堂Windows打印管理在Linux平台实现
设置好 IPP 请求之后,通过函数 cupsDoRequest() 就可以把指定IPP请求发送到服务器端。如果请求发送成功,那么请求发送方将得到有效的IPP应答pIPPRes。需要指出的是,即使 IPP 应答有效,也并不意味着所有 IPP 请求的内容都得到了正确的回复。还需要进一步检查 IPP 应答的状态代码 "request.status.status_code" 来核实反馈信息的有效性。
ipp_t *pIPPRes = cupsDoRequest(pHTTPConnection, pIPPReq, "/"); if (!pIPPRes) { g_print("No response from CUPS server\\n"); return 0; } if (pIPPRes->request.status.status_code > IPP_OK_CONFLICT) { printf("IPP Error: %s\\n", ippErrorString(pIPPRes->request.status.status_code)); ippDelete(pIPPRes); return 0; }
5.5获取 IPP 应答
如果上述操作都成功返回,就可以进一步从 pIPPRes 结构中提取感兴趣的信息。在下列代码中,变量 pPrinterName,pPortName 和 pPrinterModel 分别用来存储打印机名称,打印机端口号和打印机的类型信息。通过依次枚举 IPP 应答 pIPPRes 来寻找属性 pAttr->name 为 "printer-name" 或 "device-uri" 或 "printer-make-and-model" 的分量,就可以得到上述信息。
char *pPrinterName = NULL; char *pPortName = NULL; char *pPrinterModel = NULL; for (ipp_attribute_t *pAttr = pIPPRes->attrs; pAttr != NULL; pAttr = pAttr->next) { if (pAttr->group_tag == IPP_TAG_PRINTER) { if (0 == strcmp(pAttr->name, "printer-name")) pPrinterName = pAttr->values->string.text; if (0 == strcmp(pAttr->name, "device-uri")) pPortName = pAttr->values->string.text; if (0 == strcmp(pAttr->name, "printer-make-and-model")) pPrinterModel = pAttr->values->string.text; } }
5.6释放内存
最后,需要释放相关内存以免内存泄露:
httpClose(pHTTPConnection); ippDelete(pIPPRes);
6字符编码转换
在实现打印机管理的移植过程中,还需要特别注意字符编码转换的问题。当然,字符编码问题不仅仅局限于本文所探讨的范畴,它同时还是所有应用程序移植都需要特别关注的技术细节。以本文为例,在 Linux 上获取的字符串,比如打印机名称,通常是 UTF-8(Unicode Transformation Format) 编码的。
而 Windows 应用程序并不使用 UTF-8 编码。由于历史原因,Windows 程序或使用 ANSI 编码方式,或使用UTF-16 编码方式。因此,从 CUPS 获取的字符串还需要根据程序运行环境进行编码转换,之后才能被 Windows 应用程序使用。字符编码转换可以使用 IBM ICU(International Components for Unicode)来完成。
7.结束语
移植是一项实现应用程序跨平台运行的核心技术。本文重点阐述了 Windows 打印机管理系统在 Linux 平台上的移植技术。通过具体举例,本文详细分析了打印机管理在 Linux 平台上的移植细节。
本章涉及的移植架构和移植概念不仅仅局限于打印机管理移植。这些概念和思想也是所有应用程序所通用的。应用程序跨平台移植已经在很多软件中被应用。实现应用程序在不同平台上无缝隙的运行操作也将是每位移植技术人员的共同目标。