2 回答
TA贡献1868条经验 获得超4个赞
您不能在不自己编写 C 包装器 (+ cgo) 或使用 SWIG 的情况下调用 C++ 代码,遗憾的是它就是这样。
你链接的那个帖子已经过时了,不能再使用了。
另一方面,你总是可以在纯 Go 中开始重写 opencv,速度差异不会那么大,特别是如果你学会了如何使用 unsafe 来处理速度关键部分。
不建议使用 unsafe 的免责声明,因为它是不安全的。
TA贡献1848条经验 获得超10个赞
你可以这样做,为了我自己的目的,我已经将 OpenCV 的一个非常简单的子集移植到 Go 中。通常,该过程是分配堆上的所有内容并将其作为 typedef'd 返回void*。例如:
typedef void* gocv_matrix;
从那里开始,您的很多工作都是直通函数。一个非常重要的注意事项是您的头文件必须是纯 C 并且只能(递归地)包含纯 C 的头文件。这意味着您的标头将主要是原型/前向声明。
所以标题中的一些 Matrix 方法mat.h可能看起来像
gocv_matrix newMatrix();
void add(gocv_matrix m1, gocv_matrix m2, gocv_matrix dst);
void destroy(gocv_matrix m);
然后你的实现mat.cxx看起来像
//include all relevant C++ OpenCV headers directly
gocv_matrix newMatrix() {
cv::Matrix *mat = new cv::Matrix();
return (gocv_matrix)mat;
}
void add(gocv_matrix m1, gocv_matrix m2, gocv_matrix dst) {
cv::Matrix *a = (cv::Matrix *)m1;
cv::Matrix *b = (cv::Matrix *)m2;
cv::Matrix *dstMat = (cv::Matrix *)dst;
(*dstMat) = (*a)+(*b);
}
void destroy(gocv_matrix m) {
cv::Matrix *a = (cv::Matrix *)(m1);
delete a;
}
(免责声明:这里的确切代码没有经过正确性验证,这只是要点)。
一些特别的注意事项:
确保你有一个你实际调用的销毁方法,否则你会泄漏内存。
由于 C 和 C++ 常量与 Go 常量不同,因此您必须将它们声明为var而不是const.
OpenCV 的一些常量包含在不是纯 C 的头文件中,这使得在 Go 中定义它们变得非常困难。我在一些图像处理子包中注意到了这一点。
请注意缺少模板化泛型。通常,您要么完全放弃模板,为每个可能的实例定义不同的类型,要么选择一个(可能是两倍,可能是用于显示图像的 int 大小)并坚持使用它。
请注意,您不能以这种方式使用重载运算符。所以 a+b*c 是 b.Mul(c).Add(a)。从理论上讲,您可以发明一些表达式解析器,它接受像 "a+(b*c)" 这样的字符串和矩阵列表,然后进行一些调用批处理,但是如果您当时处于开发阶段,您就不会问这个问题。
这通常对于 cgo 来说是正常的,但是您可能会经常使用 unsafe,特别是如果您想直接使用矩阵的原始支持数据。您可以通过使您的 Go 级别Mytype类型成为包含 aC.mytype而不是实际转换它的简单结构来稍微减少这种情况。
老实说,你可能应该只使用 SWIG,因为这基本上已经为你做了什么,除了额外的细节,比如在大多数情况下为你生成实际的 Go 常量而不是粗略的 var 魔法。
- 2 回答
- 0 关注
- 276 浏览
添加回答
举报