读码器 C++ 封装
设备枚举、开停流、GigE 改 IP、GenICam 写参与读码回调;面向客户端进程内集成。
稳定 C ABI
hik_cr_* 与线程局部错误信息,便于 ctypes / cgo 等 FFI 安全调用。
Python & Go
正式包 hik-code-reader(wheel 内嵌 DLL);Go 子模块在 ffi/go。
分发方式
Release 附件 + 本站的 PEP 503 索引;Go 使用 go get 与 ffi/go/v* 标签。
快速安装(示例)
以下为典型写法;版本号与 tag 对应,请以 Releases 与 README 为准。当前平台主要为 Windows x64。
Python(PEP 503)
pip install "hik-code-reader==<版本>" \ --index-url "https://snippet0809.github.io/hik-mvcamera-control/simple/" \ --trusted-host "snippet0809.github.io"
Go
go get github.com/snippet0809/hik-mvcamera-control/ffi/go@<tag 或 main>
完整说明(README)
以下内容由仓库根目录 README.md 自动生成;更新 README 并推送到默认分支后,由 Pages (README) 工作流刷新本页。
围绕海康机器人 机器视觉 SDK 的本地封装与工程骨架:仓库已包含 读码器(MvCodeReader) 与 工业相机(MvCamera) 两套 SDK 的头文件与导入库,src/code_reader/ 与 src/mvcamera/ 各是一套 C++ 封装(设备枚举、开关流、网络与参数设置等),并带有基于 GoogleTest 的 CMake 测试目标。对外提供 稳定 C ABI(hik_cr_* / hik_cv_*),便于 Python(ctypes)、Go(cgo) 与 Node(N-API,统一包 ffi/node → hik-mvcamera-control) 等语言加载 hik_code_reader.dll / hik_mvcamera.dll 共享库调用。
项目架构(分层与自动化)
运行时与代码分层
自底向上:厂商 SDK(include/、lib/ 中海康头文件与导入库)→ src/code_reader/ / src/mvcamera/ C++ 封装(设备、参数、回调等)→ 导出 DLL hik_code_reader.dll(hik_cr_*)/ hik_mvcamera.dll(hik_cv_*)→ 上层语言通过 FFI 加载 DLL:
flowchart TB
SDK["海康机器视觉 SDK\nMvCodeReader + MvCamera\n头文件 / .lib"]
CPPR["C++ 封装\nsrc/code_reader/"]
CPPM["C++ 封装\nsrc/mvcamera/"]
CAPI["C ABI\nhik_cr_* / hik_cv_*"]
DLLR["hik_code_reader.dll"]
DLLM["hik_mvcamera.dll"]
PY["python/hik_code_reader\n正式 wheel(读码器)"]
G["hikcr / hikcv\ncgo(读码器 / 相机)"]
PYref["ffi/python\nctypes 参考(读码器)"]
NODE["ffi/node\nhik-mvcamera-control\n(读码器 + 相机)"]
SDK --> CPPR --> CAPI --> DLLR
SDK --> CPPM --> CAPI --> DLLM
DLLR --> PY
DLLR --> G
DLLR -.-> PYref
DLLR --> NODE
DLLM --> NODE
- 构建:根目录 CMake 生成静态库、测试与 共享库(目标名见
CMakeLists.txt)。 - Python 正式包:
python/下build打 wheel,release.yml发版仅将hik_code_reader.dll与海康lib/MvCodeReader/win64/*.lib拷入hik_code_reader/_native/;不把海康运行时 DLL 绑在「开发机是否安装 MVS」上。终端环境通过安装 MVS/IDMVS Runtime 或你方专用打包流水线(自托管 Runner、私有制品等)提供MvCodeReaderCtrl.dll等。Go 侧自 2026-09-12 起采用同一口径(见下文「Go 开发者」)。 - Go:
hikcr/hikcv通过 cgo 链接runtime/里已构建的转发库。Windows 侧的海康运行时由使用方自行安装 MVS/IDMVS 提供(与 Python 侧同一口径),Linux 侧仍随包分发;两条路线的取舍与验收手段见下文「Go 开发者」。转发库仍由 CMake+MSVC 编出,cgo 编译 C 片段需 GCC 类工具链(如 MinGW 的gcc),勿将CC设为cl(见go.dev/issue/20982)。
GitHub Actions 在流程中的位置
| 环节 | Workflow | 作用(简述) |
|---|---|---|
| 发版 | release.yml |
打 tag v* → 同步 pyproject 版本、构建产物、GitHub Release(含运行时包)、gh-pages(含 PEP 503 + 主页);另有 build-linux 作业构建并校验 Linux .so。 |
| 文档页增量 | pages-readme.yml |
仅 main/master 上 README 或 .github/scripts/ 变更时,重生成 主页 index.html,保留已有 simple/。 |
站点生成脚本的模块关系、环境变量与两种模式说明见 .github/scripts/README.md(与根 README 互补:根文档讲「产品」,该文件讲「Pages 构建脚本怎么拼在一起」)。
功能概览(读码器 C++ 封装)
- 枚举设备:
enumDevice(),返回序列号、GigE 导出 IP 与设备型号(modelName,如MV-IDB005EX=读码器、MV-CU013=相机)等信息(见src/code_reader/device_info.cpp)。> 注意:海康 GigE 枚举会把同网段读码器与工业相机一并列出,靠型号区分。 - 运行控制:
startDevice/stopDevice(内部完成打开设备、可选CodeReaderOpenParams、BCR 回调与起停流等;按序列号操作)。 - 读码回调:通过
startDevice第三参传入;std::nullopt保留已有登记,空std::function可取消该序列号回调。软触发:triggerDevice(仅当设备处于取流 Grabbing)。 - 改参 / GenICam:
startDevice第二参CodeReaderOpenParams含默认值,起流前写入;按需覆盖各成员即可。另提供与相机同构的参数读写setReaderParam/getReaderParam/runReaderCommand(C ABI:hik_cr_set_param/hik_cr_get_param/hik_cr_set_param_string/hik_cr_get_param_string),可按 GenICam 节点名读写 Int/Float/Bool/Enum/String 并执行命令节点(如TriggerSoftware)。 - GigE 枚举:
enumDevice/hik_cr_enum_devices仍返回当前 导出 IP(netExportIp)等摘要,便于展示与日志;本库不再提供改 IP 的封装。 - BCR 回调指针生命周期:
hik_cr_start_device的 BCR 回调传出的codes指针指向 SDK 保留到「下次解码」的结果,在回调返回后仍短暂有效,供把回调排队的 FFI(koffi→JS 主线程、ctypes 异步等)延迟消费;同步消费(cgo)行为不变。 - C API / FFI:C 函数前缀
hik_cr_*,返回HikCrResult,错误信息用hik_cr_last_error_copy按线程读取。正式发布用python/hik_code_reader(wheel 内嵌 DLL);ffi/python为同逻辑参考副本。Go 见hikcr/(读码器)与hikcv/(相机)。
在 GitHub 上托管分发(维护者)
GitHub Packages 没有与 PyPI 对等的 Python 包仓,也没有替代 go get 的独立 Go Registry。本仓库采用 「Releases + GitHub Pages(PEP 503)+ Git 标签」,全部留在 GitHub 上完成托管。
原理简述
| 对象 | 托管位置 | 作用 |
|---|---|---|
| Python wheel | GitHub Releases 附件 | 真实安装包;pip 最终下载的文件 |
pip search 式索引 |
GitHub Pages(gh-pages 分支的 simple/) |
符合 PEP 503,让开发者能用 pip install 包名==版本 --index-url ... |
| Go 源码模块 | 本仓库 Git + 标签 vX.Y.Z(模块根即仓库根) |
go get 经官方模块代理从 GitHub 拉取 |
维护者一次性配置
- 保证仓库根
go.mod第一行与 GitHub 仓库路径一致。本仓库应为:
module github.com/snippet0809/hik-mvcamera-control
(若 fork 后自用,请改为github.com/<你的用户名>/hik-mvcamera-control。)
模块根即仓库根,所以vX.Y.Z标签本身就是模块版本,不再需要单独的ffi/go/v*标签。 - 在 GitHub 打开本仓库:Settings → Pages
- Build and deployment:Source 选 Deploy from a branch
- Branch 选
gh-pages,文件夹选/(root) - 保存。首次需等
release.yml成功跑过一次 后才有gh-pages分支。
维护者发版步骤
- 在默认分支上确认代码与
python/pyproject.toml已就绪。 - 创建并推送 语义化标签(必须以
v开头):
git tag v0.0.2 && git push origin v0.0.2 - GitHub Actions 中
Release工作流(release.yml)会自动: - 将
python/pyproject.toml里的version改成与标签一致(去掉v,如v0.0.2→0.0.2),再构建 Windows x64 wheel(_native/内含hik_code_reader.dll与海康MvCodeReaderCtrl.lib/turbojpeg.lib); - 创建/更新 GitHub Release,并上传 wheel、
hik_code_reader.dll/hik_code_reader.lib及上述厂商.lib,以及运行时压缩包runtime/(Linux 侧解压即用;Windows 侧只含本项目 wrapper); - 生成 PEP 503 页面并推送到
gh-pages(与已有索引合并,保留历史版本链接); - 跑
scripts/verify-runtime.sh(哈希 + ABI 三重守卫)——头与二进制对不上时宁可不发版。 - 不再创建
ffi/go/v*标签:Go 模块根已抬到仓库根,vX.Y.Z标签本身就是模块版本。
发版后维护者自检
- Releases 页面是否出现新版本,且附件中有
.whl。 - Actions 里
Release是否全部绿色。 - Settings → Pages 是否显示站点地址(约
https://<用户>.github.io/<仓库名>/)。 - 浏览器打开
https://<用户>.github.io/<仓库名>/simple/hik-code-reader/,应能看到指向 Release 的链接。
开发者使用指南
以下示例以本仓库 github.com/snippet0809/hik-mvcamera-control 为准;若你 fork 或改名,请替换路径中的用户名与仓库名。
Python 开发者
环境:当前 wheel 为 Windows x64(文件名中含 win_amd64),需在对应环境安装。
方式 A:从 GitHub Release 直链安装 wheel(不依赖 Pages,最省事)
- 打开本仓库 Releases,选择对应版本(如
v0.0.2)。 - 在 Assets 里找到
hik_code_reader-…-py3-none-win_amd64.whl,复制其「直链」;或直接使用与 tag、版本一致的 URL(tag 带v,包版本号无v):
pip install "https://github.com/snippet0809/hik-mvcamera-control/releases/download/v0.0.2/hik_code_reader-0.0.2-py3-none-win_amd64.whl"
其它版本请把 URL 中的 v0.0.2 / 0.0.2 换成你的 tag 与 pyproject 版本;wheel 完整文件名以该 Release 页 Assets 为准。
方式 B:像「私有 PyPI 源」一样用 PEP 503(依赖 Pages)
在维护者已开启 GitHub Pages(gh-pages)且发过版的前提下:
pip install "hik-code-reader==0.0.2" \
--index-url "https://snippet0809.github.io/hik-mvcamera-control/simple/" \
--trusted-host "snippet0809.github.io"
- 版本号
0.0.2与 Git 标签v0.0.2对应(无v)。 --trusted-host在部分企业网络下必填;若 pip 仍报错,请检查 HTTPS 与防火墙。- 首次如何开 Pages、索引如何生成,见上文 「在 GitHub 上托管分发」 与 README 中维护者章节。
代码示例:
from hik_code_reader import HikCodeReader
cr = HikCodeReader() # wheel 内有 hik_code_reader.dll;MvCodeReaderCtrl 等 DLL 由本机 Runtime 或你方部署方式提供
print(cr.enum_devices())
pip 安装后提示找不到 DLL / WinError 126 / 0xc0000135
- 公共 wheel 不含海康运行时
*.dll(打包流程不假设维护者电脑装了 MVS)。请在 运行工控机 上安装 MVS/IDMVS RunTime(或与 SDK 版本匹配的官方运行库),使Path/GENICAM_GENTL64_PATH/MVCAM_GENICAM_CLPROTOCOL等到位。 - 若你要 免安装分发:在你方固定版本、可复现的打包环境(例如已装对应 MVS 的 自托管 Runner、或从私有制品库取与 SDK 锁定的 DLL 集)里组装配应用,不要依赖「开发 SDK 的那台 PC」是否装了 Runtime。
- Python(Windows)在
ctypes加载前:将hik_code_reader.dll所在目录置于PATH与add_dll_directory优先,再补充上述海康变量与Path中含MVS/IDMVS/MvSDK/MvCode的目录;并使用LoadLibraryEx标志,便于把MvCodeReaderCtrl.dll等与hik_code_reader.dll放在同一目录时能被解析。 - 若仍失败:用依赖查看工具打开
hik_code_reader.dll核对缺失的.dll;并确认 VC++ x64 运行库已安装。
Go 开发者
模块路径(go.mod 在仓库根):
github.com/snippet0809/hik-mvcamera-control
安装:
go get github.com/snippet0809/hik-mvcamera-control@v0.2.0
代码中导入:
import (
"github.com/snippet0809/hik-mvcamera-control/hikcr" // 读码器
"github.com/snippet0809/hik-mvcamera-control/hikcv" // 相机
)
破坏性变更:早先的模块路径是
.../hik-mvcamera-control/ffi/go,包在.../ffi/go/hikcr。
现已抬到仓库根,导入路径变成.../hikcr与.../hikcv,已有的import与require都要改。
那次搬迁同时修好了两个让go get根本编不过的问题——旧的 cgo 头路径落在模块根之外
(模块 zip 拿不到include/),且参数读写直接写了cv.type(type是 Go 保留字)
与匿名 union 成员。旧路径任何时候都没有真正可用过。⚠️ 待补的 API(2026-09-15 记录,本次未实现)
Go 绑定落后于 C ABI,有 4 个函数尚未暴露。以后要用 Go 时按需补齐:
C ABI(头里已声明) 归属 Go 现状 hik_cv_encode_jpeg相机 hikcv无 → 需加EncodeJpeghik_cr_get_bcr_image读码器 hikcr无 → 需加GetBcrImagehik_cr_stop_grabbing读码器 hikcr无 → 需加StopGrabbinghik_cr_set_frame_callback读码器 hikcr无 → 需加SetFrameCallback现在
go build ./...仍能通过(Go 侧根本没引用这些符号),所以这个缺口是静默的。补之前必须先刷新
runtime/的 wrapper:runtime/include/hik_mvcamera/c_api.h
已声明hik_cv_encode_jpeg,但runtime/windows-x86_64/lib/hik_mvcamera.lib没有导出它
——这就是scripts/verify-runtime.sh要抓的「头新库旧」。读码器侧runtime/的三个符号是齐的,
只有相机侧缺这一个。不先刷新,hikcv一旦加上EncodeJpeg,go build会直接链接失败。
链接模型:构建期与运行期分开看。
构建期只依赖本项目自己的东西——头在 runtime/include,导入库在
runtime/windows-x86_64/lib,cgo 参数直接指向它们:
#cgo CFLAGS: -I${SRCDIR}/../runtime/include
#cgo windows LDFLAGS: -L${SRCDIR}/../runtime/windows-x86_64/lib -lhik_code_reader
#cgo linux LDFLAGS: ... -Wl,-rpath,$ORIGIN/runtime/linux-x86_64/lib -Wl,--disable-new-dtags
运行期按平台分了不同路线(这是既定方案,不是可选项;两条路线可混用,exe 同目录优先):
| 平台 | 路线 | 谁提供海康运行时 |
|---|---|---|
| Windows | 使用方自行安装 | MVS(相机)+ IDMVS(读码器),x64。安装器会写机器级 PATH,进程启动时继承 |
| Linux | 随包分发 | runtime/linux-x86_64/lib/ 里的副本,与 exe 保持 $ORIGIN 相对位置,使用方无需安装任何东西 |
为什么不按同一套口径:判据是「要的东西能不能随包走」。Linux 要的是用户态 .so(能随包,RPATH 就能解析,且 Linux 侧 GigE 直接走内核 UDP 栈、没有过滤驱动这回事);Windows 要拿到 GigE 过滤驱动 neugevfilter ——那是签名内核驱动,只能靠安装(管理员 + 重启),随包拿不到。所以不对称是被这个约束逼出来的,代价必须认:Windows 侧的版本由使用方决定,交付时按 runtime/VERSION 记的厂商版本对齐,并用下节的 hikprobe 确认实际用的是哪一套。
Windows + 已装 SDK:exe 旁只需要 hik_code_reader.dll 与 hik_mvcamera.dll。
cgo 把这两个 wrapper 写进 exe 的 PE 导入表,它们又静态导入 MvCodeReaderCtrl.dll /
MVCameraControl.dll,ntdll 在任何 Go 代码运行之前就要解析这一串;能解析的前提是
「exe 同目录」或「进程启动前已在 PATH 上」,而 MVS/IDMVS 安装器把运行时目录写进
机器级 PATH,进程启动时继承下来——整条链就自动打通了(实测:exe 旁只放两个 wrapper,
枚举与取流均正常,走 driver 模式)。
两个好处:拿到 GigE 过滤驱动(否则只能 socket 模式),以及不必在每个 exe 旁维护
35 个厂商文件。代价是版本由使用方决定,对策见下节。
Linux:runtime/linux-x86_64/lib/ 与可执行文件保持 $ORIGIN 相对位置即可
(厂商 .so 随仓库分发,不是可选项)。万一你把二进制挪到别处,兜底是
LD_LIBRARY_PATH=<...>/linux-x86_64/lib。
坑:
$ORIGIN要写本字,不能写成$$ORIGIN。 cgo 不做 Makefile 那套$$转义,
-Wl,-rpath,$$ORIGIN/...会原样落进DT_RPATH;而 ld.so 只认$ORIGIN,遇到
$$ORIGIN会把后半截按$ORIGIN展开、把第一个$当字面量留下,得到
$/home/you/app/...这种不存在的路径,随包.so全部解析失败。表现是ldd报
not found、「解压即用」名存实亡,只能靠LD_LIBRARY_PATH兜底。
构建期完全静默——go build一路绿灯,所以链接后务必核对:
readelf -d hikprobe | grep -i rpath须打印字面$ORIGIN。
这个坑曾真实存在(2026-09-12 真机发现并修复),而 C++ 侧的all_tests用的是绝对
路径 RPATH,一直能跑,恰好把它盖住了。
平台与工具链:
- 仅支持 windows/amd64 与 linux/amd64(
runtime/里的厂商二进制只有这两个)。
其余平台会命中空包 stub,go build不会失败,但调用点会报undefined。 - 需要
CGO_ENABLED=1与 gcc/clang 工具链。Windows 下 C 编译器用 MinGWgcc等,
勿设CC=cl(见go.dev/issue/20982)。 - cgo 不能交叉编译:要在 Linux 上跑就在 Linux 上编。
验收:cmd/hikprobe
go build -o hikprobe.exe ./cmd/hikprobe
# Windows(既定:使用方自装 MVS/IDMVS):exe 旁只放两个 wrapper
copy ..\runtime\windows-x86_64\bin\hik_*.dll .
.\hikprobe.exe # 默认 -net=auto,随 SDK 默认走 GigE 过滤驱动(装了 MVS 就有)
.\hikprobe.exe -net=socket # 诊断用:拿不到过滤驱动时到底能不能取流
# Linux(随包分发):保持 runtime/ 与二进制的相对位置,无需安装任何东西
go build -o hikprobe ./cmd/hikprobe
readelf -d hikprobe | grep -i rpath # 先确认是字面 $ORIGIN,见上文那个坑
./hikprobe # 不设 LD_LIBRARY_PATH 也应能解析到随包 .so
它枚举读码器与相机、对找到的相机起流软触发取帧,并列出本进程已加载的非系统模块
及其来源(exe 目录 / 其他位置)——看一眼就知道这次实际用的是哪一套运行时:
- Windows:海康模块来自
Common Files\MVS与IDMVS\...\mvsidcamctrl是预期结果
(走的就是使用方装的那套)。 - Linux:海康模块应落在 exe 目录之内(随包分发,靠
DT_RPATH=$ORIGIN解析)。
它还会先打印相机的采集节奏(ExposureTime / ResultingFrameRate),再按实际帧率放宽
软触发间隔——快于采集周期的触发会被相机直接丢弃,不这样处理会把正常现象误判成丢帧
(实测:曝光 500ms 时相机只有 1.66fps,300ms 间隔触发 3 次只能收到 2 帧)。
Linux 真机基线(2026-09-12,Debian 12 / kernel 6.1 / glibc 2.36,相机 MV-CU120-10GC
走 GigE):枚举、起流、软触发 3/3 帧,4024x3036 BayerRG8、payload 12216864;
-net=auto 即可(Linux 无过滤驱动,GigE 直接走内核 UDP 栈);已加载的非系统模块 8 个
全部落在 exe 目录内,且未设 LD_LIBRARY_PATH(即 $ORIGIN 真正生效)。
bash scripts/verify-runtime.sh 亦全绿(25 个哈希 + 两平台各两库的符号比对)。
这条路线可作回归基线。
注:
hikprobe的读码器枚举会把 GigE 相机一并列出来——IDMVS 读码器 SDK 的枚举
不过滤机型,双方互相枚举是它的既有行为,不是本项目的问题。
私有仓库:go env -w GOPRIVATE=github.com/snippet0809/*,必要时配置 SSH 或带 token 的 HTTPS。
GitHub Actions 摘要
| Workflow | 说明 |
|---|---|
Release(.github/workflows/release.yml) |
推送 v*.*.*:GitHub Release 附件(含运行时包 runtime/)、gh-pages(更新 pip 用 simple/ 与根目录 README 页);build-linux 作业另建 Linux .so 并跑 verify-runtime.sh。 |
Pages (README)(.github/workflows/pages-readme.yml) |
推送到 main/master 且变更 README.md 或 .github/scripts/ 下站点生成脚本时:只重部署 根 index.html(入口为 generate_pages_site.py),keep_files 保留 simple/。 |
仓库结构
| 路径 | 说明 |
|---|---|
src/code_reader/ |
读码器 C++ 封装实现(code_reader.h、c_api.cpp 等) |
include/hik_code_reader/ |
C ABI 头文件(c_api.h),供 Python/Go 等包含 |
python/ |
hik-code-reader 包与 pyproject.toml(wheel 的 _native/ 含 DLL 与海康 win64 导入库) |
ffi/python/ |
ctypes 参考实现(与 python/hik_code_reader 保持同步为佳) |
go.mod(仓库根) |
Go 模块根(模块路径即仓库路径) |
hikcr/、hikcv/ |
Go 包:读码器、相机(cgo,链接 runtime/) |
runtime/ |
头文件 + 本项目 wrapper + Linux 侧随包的厂商运行时;来源与哈希见 runtime/VERSION、runtime/MANIFEST.sha256。Windows 侧厂商运行时不在此(由使用方装 MVS/IDMVS 提供) |
internal/hikdll/ |
Windows 下登记厂商 DLL 搜索目录(hikcr/hikcv 共用) |
cmd/hikprobe/ |
设备验收探针(枚举/起流取帧 + 已加载模块来源) |
scripts/verify-runtime.sh |
校验 runtime/:哈希 + ABI 三重守卫 |
ffi/node/ |
统一 npm 包 hik-mvcamera-control(node-addon-api):单插件同时导出读码器(HikCodeReader)与相机(HikCamera);预编译 .node + 读码器/相机运行时全捆绑 |
include/MvCamera/、include/MvCodeReader/ |
海康 SDK 头文件 |
lib/MvCamera/{win32,win64}/、lib/MvCodeReader/{win32,win64}/ |
预置静态库(含 turbojpeg 等读码器依赖) |
tests/ |
GTest 用例(需连接真实设备时谨慎运行) |
.docs/ |
本地文档(如读码器开发指南 CHM) |
构建要求
- CMake 4.0 及以上(见根目录
CMakeLists.txt)。 - 支持 C++17 的 MSVC(当前工程通过
FetchContent拉取 GoogleTest)。 - Windows:默认链接
lib/MvCodeReader/win64/MvCodeReaderCtrl.lib;若在 32 位环境构建,需自行将 CMake 中的库路径改为win32对应文件。
工具链怎么选:wrapper 用 MSVC,cgo 用 MinGW
构建 hik_code_reader.dll / hik_mvcamera.dll 请用 MSVC。
gcc(MinGW) 也能编——GNU ld 直接读海康那两个 MSVC 导入库没问题,导出符号与 MSVC 逐字节一致
(13/13 未修饰同名)。但默认配置下它会静默产生错误数据:海康 PixelType.h 用
#ifdef WIN32 在两种定义间切换,而 MinGW 只定义 _WIN32、不定义 WIN32,于是
MvGvspPixelType 从 4 字节变 8 字节,MV_FRAME_OUT_INFO_EX 之后所有字段整体错位——
width/height 恰好还对(它们在结构体开头),但 frameLen 读成 0、frameNum 是垃圾值。
要修得加两个定义(CMake 的 if(MINGW) 分支已代劳):WIN32(让枚举回到 4 字节),
以及 -D__int64="long long"(WIN32 分支里写的是 MSVC 专有的 typedef __int64 int64_t;,
MinGW 的 gcc 不认)。另需去掉产物名的 lib 前缀、并把 GCC 运行库静态并入。
即便修好,这个位置仍是脆的:它依赖厂商头的 ifdef 写法,海康更新 SDK 可能重新错位。
tests/mvcamera_test.cpp 里有逐帧元数据断言专门守这一点(校验 frameLen 与 宽x高 自洽),
但选与厂商相同的工具链仍然更省心——wrapper 很少重新编译,MSVC 构建慢一点也不重要。
cgo 则必须用 MinGW:Go 在 Windows 上的 cgo 不能用 cl(见 go.dev/issue/20982),
所以 Go 使用者无论如何都要装 gcc 类工具链。两个工具链并存是正常状态,不是妥协。
构建与测试
# MSVC(推荐)。生成器名跟本机 VS 版本走,用 cmake --help 查:
# VS 2026 -> "Visual Studio 18 2026";VS 2022 -> "Visual Studio 17 2022"
cmake -S . -B build-vs -G "Visual Studio 18 2026" -A x64
cmake --build build-vs --config Release
ctest --test-dir build-vs -C Release
# MinGW(可用,但请先读上文的限制)
cmake -S . -B build-mingw -G Ninja -DCMAKE_BUILD_TYPE=Release `
-DCMAKE_C_COMPILER=D:/mingw64/bin/gcc.exe -DCMAKE_CXX_COMPILER=D:/mingw64/bin/g++.exe
cmake --build build-mingw
用 MSVC 但想走 Ninja(需已安装 Ninja 且在同一 shell 中加载 MSVC 环境):
cmake -S . -B build-ninja -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build-ninja
首次配置会从网络下载 GTest;需保证构建环境可访问 GitHub。
产物说明:
hik_code_reader_static.lib/hik_mvcamera_static.lib:静态库,供all_tests等链接。hik_code_reader.dll(目标hik_code_reader_shared,导出hik_cr_*)与hik_mvcamera.dll(目标hik_mvcamera_shared,导出hik_cv_*):共享库供 FFI。Python 可将环境变量HIK_CODE_READER_DLL设为读码器 DLL 的完整路径,或把 DLL 放到进程当前目录 /PATH;Node 统一包ffi/node(hik-mvcamera-control)直接捆绑两个 DLL 与海康读码器/相机运行时。- 发版产物:见上文 Release / gh-pages。
运行与部署说明
- 在目标机器安装海康读码器/视觉设备所需 驱动与运行库(版本需与 SDK 匹配)。
Windows 的 Go 部署就是装 MVS(相机)+ IDMVS(读码器),x64,版本按runtime/VERSION对齐。 - GigE 设备注意网卡、防火墙与网段;改 IP 请使用海康官方工具/SDK,本仓库封装不再提供
setIp。 - 装完跑一次
hikprobe(见「Go 开发者 → 验收」)确认两件事:海康模块来自已安装的
MVS/IDMVS 目录(而不是别处),以及相机能起流、软触发能收到帧。 - 若 SDK 装在非标准位置,把对应的 DLL/
.so放到可执行文件同目录,或用既有的
HIK_CODE_READER_DLL/HIK_MVCAMERA_DLL指向。
读码器 SDK 使用要点(与 .docs 开发指南 CHM 一致)
以下摘要自海康读码器 SDK 开发指南,使用本封装或直连 MvCodeReader 前请一并遵守:
- GigE 网口巨帧:使用前需先在网卡上开启 巨帧(Jumbo Frame),否则大包/高负载下易丢包或异常。
- RunTime 包:需安装与目标程序 位数一致(32 位 / 64 位)的 工业相机 SDK RunTime,且版本为 RunTime 3.0.0 及以上。
- 回调与轮询互斥:回调类接口与 轮询类接口不能同时用来取图;二者二选一,不可混用。
- 多路回调:对指定流通道调用底层
MV_CODEREADER_MSC_RegisterImageCallBack()可注册回调;可对多路流通道分别注册,以同时获取多路图像与条码结果。 - 多路轮询:
MV_CODEREADER_MSC_GetOneFrameTimeout()可按通道轮询取图;可对多路流通道分别轮询,以同时获取多路数据。
本仓库 C++ 封装在取流路径上主要采用 回调 模式(如 BCR 回调);若你在同进程内再调官方 轮询 接口,须遵守上述互斥约定。更细的参数与流程以 CHM / 官方 PDF 为准。
Windows:RunTime 位置与「环境变量」说明
海康 MVS / IDMVS / RunTime 安装器一般会同时:
- 写入
PATH(RunTime、IDMVS\...\MvSDK等); - 写入 GenICam / MVS 相关变量(示例,以你机为准):
GENICAM_GENTL64_PATH、GENICAM_GENTL32_PATH、MVCAM_GENICAM_CLPROTOCOL等。
python/hik_code_reader 在 Windows 上会读取上述 路径型官方变量 及 Path 中的 MVS/IDMVS 相关目录,用于 os.add_dll_directory(见包内实现)。仍仅保留本仓库自有的 HIK_CODE_READER_DLL(仅指向 hik_code_reader.dll 本身,可选)。
自查 PATH 里与厂商相关的项(PowerShell,合并用户级与机器级):
('Machine','User') | ForEach-Object {
[Environment]::GetEnvironmentVariable('Path', $_) -split ';' |
Where-Object { $_ -match '(?i)MVS|MvCode|IDMVS|Hik|HIKROBOT|Runtime|Common Files\\MVS' }
} | Sort-Object -Unique
自查海康常见路径型环境变量(当前进程继承的安装器配置):
'GENICAM_GENTL64_PATH','GENICAM_GENTL32_PATH','MVCAM_GENICAM_CLPROTOCOL' | ForEach-Object {
"${_}=$([Environment]::GetEnvironmentVariable($_,'Process'))"
}
常见会出现的路径形态(仅供参考,以你机器上安装版本为准):
- 含
Common Files\MVS\Runtime或Runtime\Win64等字样的目录(独立 RunTime 包或套件附带)。 - 含
MVS、Development、Bin\win64(完整开发包)或 读码器 / IDMVS 安装目录下的Bin。
若进程仍报 找不到 DLL / 0xc0000135:除检查 PATH 外,还可把缺失的 DLL 放到 hik_code_reader.dll 同目录,或确认与 RunTime 3.0.0+ 及 x64/x86 位数 一致。
许可证与第三方
海康威视 MvCamera / MvCodeReader SDK 及其文档的版权与许可归原著作权人所有;本仓库中的封装代码请以你方项目许可证为准。GoogleTest 遵循其开源协议(由 CMake FetchContent 获取)。
相关文档
- 读码器开发说明可参考仓库内
.docs下 CHM(读码器 SDK 开发指南) 及include/MvCodeReader头文件中的 API 定义(如MV_CODEREADER_MSC_*)。