Linux 版的 wsdl2h 命令和 Windows 版只差三处,
而其中最坑的是「反斜杠」——因为它在 shell 里是转义字符。
另外 Linux 的库搜索路径里没有「当前目录」,这是和 Windows 最大的观念差。
上一节把 typemap.dat 的换行问题解决了,这一节真正跑生成命令。
命令本身和 08.01.04 一样,
但 shell 会把某些字符吃掉——这一节讲的就是「被吃掉的那部分」。
一、三处差别
| 项 | Windows | Linux |
|---|---|---|
| 可执行文件名 | wsdl2h.exe |
wsdl2h |
| 路径分隔符 | wsdl\devicemgmt.wsdl |
wsdl/devicemgmt.wsdl |
| 找动态库 | exe 同目录优先 | LD_LIBRARY_PATH 或 ldconfig |
第二行看着是小事,其实最容易错:反斜杠在 shell 里是转义字符,
wsdl\devicemgmt.wsdl 会被吃成 wsdldevicemgmt.wsdl——
然后报「文件不存在」,而你在文件管理器里明明看得见它。
第三行是观念差:Windows 会先找 exe 同目录,
Linux 不会——它只按 LD_LIBRARY_PATH、/etc/ld.so.cache、/lib、/usr/lib 这几处找。
所以「我把 .so 放在程序旁边了」在 Linux 上不管用,这是从 Windows 转过来最不习惯的一点。
二、shell 会吃掉什么
除了反斜杠,还有三个字符要小心:
| 字符 | shell 怎么处理 | 要怎么写 |
|---|---|---|
\ |
转义下一个字符 | 用 / 或写 \\ |
* |
通配符展开 | 加引号 |
| 空格 | 分词 | 加引号 |
$ |
变量替换 | 单引号或转义 |
第二行那个通配符在 ONVIF 命令里很危险:
如果参数写成 wsdl/*.wsdl,shell 会展开成 14 个文件名——
这恰好是想要的;但如果你想要的是「一个叫 *.wsdl 的文件」,就错了。
这其实是 Linux 的一个便利:批量喂 WSDL 可以写成 wsdl/*.wsdl,
不用逐个列——但要注意展开顺序不一定是你要的(按字典序)。
第三行那个空格在 Windows 用户看来不可思议(路径里有空格很常见),
而在 Linux 上「带空格的路径」必须加引号,否则会被切成两个参数。
三、-I 参数到底指哪
Linux 侧的 -I 和 Windows 侧含义一样,但「指哪」常被搞错:
| 写法 | 含义 | 对不对 |
|---|---|---|
-I import |
在当前目录下的 import/ 里找 |
对 |
-I /usr/local/gsoap/include |
绝对路径 | 对 |
-I import/wsse.h |
指到一个文件 | 错,-I 要指目录 |
第三行是最常见的错:-I 指的是「目录」不是「文件」,
指到文件上,wsdl2h 会在这个「目录」里找 wsse.h——
而那个「目录」其实是个文件,于是找不到。
报错信息是「找不到 wsse.h」,
而你已经把路径写上去了——这种「写了却没用」的错最让人怀疑人生。
第二行那个绝对路径要注意:用绝对路径的坏处是不可移植,换台机器就得改;
所以我倾向「先 cd 到工作空间根目录,然后用相对路径」。
四、生成之后先验三处
和 08.01.04 一样,生成完先验,别急着往下走:
| 验什么 | 怎么验 | 不对说明什么 |
|---|---|---|
| 文件行数 | wc -l onvif.h |
太小说明 WSDL 没读全 |
有没有 tt__ 类型 |
grep -c "_tt__" onvif.h |
0 说明 typemap 没生效 |
有没有 wsse__ |
grep -c "wsse__" onvif.h |
0 说明鉴权那行没加 |
第一行那个「太小」是个粗判据:1810 个 element 对应的头文件在万行量级,
如果 wc -l 出来只有几百行,说明大部分 WSDL 没读进去。
最常见的原因是「只喂了一个 WSDL」——命令里那一长串 URL 或路径,漏掉一个就少一大块。
第二、三行用 grep -c 数匹配行数,这是 Linux 上最快的「有没有」检查:
grep -c 返回 0 就说明一处都没有。
这三条检查加起来不到十秒,但能省掉后面「编译报一万个错」的半小时。
五、动手 Demo:Linux 下生成 onvif.h 的命令
Demo 用 Python 模拟 shell 的转义规则,看 wsdl\devicemgmt.wsdl 会被吃成什么。
这是本节唯一能「在本机复现」的现象。
arg = "wsdl\\devicemgmt.wsdl"
print(arg) # wsdl\devicemgmt.wsdl
print(arg.replace("\\", "")) # wsdldevicemgmt.wsdl
# shell 里的效果等价于「把反斜杠当转义符」
# 于是路径丢了分隔,报「文件不存在」
实跑输出:
--------------------------------------------------------------------
Linux 下生成 onvif.h 的命令
--------------------------------------------------------------------
**和 Windows 版的差别只有三处**,但每一处都会让命令跑不起来:
项 Windows Linux
-----------------------------------------------------------------------------------
可执行文件名 `wsdl2h.exe` `wsdl2h`
**路径分隔符** `wsdl\devicemgmt.wsdl` **`wsdl/devicemgmt.wsdl`**
找头文件的参数 `-I import` **`-I import`(一样)**
**运行动态库** `wsdl2h.dll` 要同目录 **要 `LD_LIBRARY_PATH` 或 ldconfig**
**第二行看着是小事,其实最容易错**:
**反斜杠在 Linux 的 shell 里是转义字符**,
**`wsdl\devicemgmt.wsdl` 会被 shell 吃成 `wsdldevicemgmt.wsdl`**,
**然后报「文件不存在」**——**而你在资源管理器里明明看得见它。**
**这是「Windows 习惯带到 Linux」的第一课**,几乎人人踩过。
**用 Python 的 shell 规则模拟一下这个转义**:
原样写:`wsdl\devicemgmt.wsdl`
经过 shell 转义后:`wsdldevicemgmt.wsdl`
**少了那个反斜杠,路径就没了分隔**,
**所以「文件不存在」的报错其实是对的。**
**第四行是第二课**:**Linux 的动态库搜索路径里没有「当前目录」**。
**Windows 会先找 exe 同目录,Linux 不会**——
**所以 `wsdl2h: error while loading shared libraries: libgsoap-2.8.116.so` 这种错**,
**解法是 `export LD_LIBRARY_PATH=/usr/local/gsoap/lib:$LD_LIBRARY_PATH`**,
**或者装完跑一次 `sudo ldconfig`。**
第二行那个 wsdldevicemgmt.wsdl 就是「文件不存在」的真相:
路径里的分隔没了,变成一个不存在的文件名。
注意这个模拟是「简化版」:真正的 shell 只会吃掉紧跟在 \ 后面的那个字符,
而这里是全删——不过结论一样:路径坏了。
所以你看到「文件不存在」但文件明明在的时候,第一件事是把命令原样 echo 一遍,
看 shell 到底把它变成了什么。
echo 是 Linux 上最被低估的调试工具:
它不执行、只回显,正好用来确认「我传进去的到底是什么」。
30 秒实验
- 在 Linux 上
echo wsdl/../wsdl/devicemgmt.wsdl,看 shell 会不会规范化路径。 - 把
-I import写成-I import/(带斜杠),看行为有没有变化。 - 跑
grep -c "_tt__" onvif.h,看数量级对不对。
常见误区
- 在 Linux 上写
wsdl\devicemgmt.wsdl。 反斜杠是转义符,路径会被吃坏, 报「文件不存在」而文件明明在。 - 把
.so放在程序旁边就以为能找到。 Linux 不搜当前目录, 要LD_LIBRARY_PATH或ldconfig。 -I指到一个文件上。 它要指目录,指到文件就找不到里面的头文件。
自测三问(点开对答案)
1. Linux 版 `wsdl2h` 和 Windows 版差哪三处? —— **可执行文件名、路径分隔符、动态库搜索路径**。 **第二项最容易错**,因为反斜杠在 shell 里是转义符。 2. 为什么 `.so` 放程序旁边找不到? —— **Linux 的动态库搜索路径里没有「当前目录」**(这是和 Windows 最大的观念差)。 3. 生成完怎么快速判断 WSDL 读全了? —— **`wc -l onvif.h` 看行数**,再用 `grep -c "_tt__"` 看类型数。 **太小就说明只读了一部分 WSDL。**下一节讲鉴权:算法不分平台,但有三个「跨平台才会犯」的错。
- ☐ (本节完,下一节 08.08.06 鉴权(认证))