1

我有一个使用 OpenCV 的 C++/CLI 项目。我自己在 VS 2010 中编译了这个版本的 OpenCV,我可以在非托管项目中毫无问题地使用它——当我尝试在托管项目中使用它时,问题就开始了。

感兴趣的函数是cv::imread(std::string&, int)。简单地从托管模块调用它根本不起作用,在接收端产生 <invalid pointer>。我有点期待它。毕竟,托管代码有自己的std::string实现。

当我创建一个单独的 C++ 文件、从其模块中删除 CLI 支持并将我的代码放入其中时,事情变得更有趣了。现在,imread得到了一个有效的指针,但它的内容被打乱了。显然,string我正在传递它包含偏移 4 个字节的字符串指针,但它希望它位于 0 偏移量。

非托管模块使用与 OpenCV 相同的 CRT DLL,并将所有选项设置为适合正常 OpenCV 使用的值。为什么会有不同的string布局?我搞不清楚了。

示例代码:

#include <opencv/cv.h>
#include <opencv/highgui.h>

#include <string>

using namespace cv;
using namespace std;

void Run()
{
    string path("C:\\Users\\Don Reba\\Pictures\\Merlin 1D.jpg");

    Mat image(imread(path, CV_LOAD_IMAGE_GRAYSCALE));
    imwrite("image.jpg", image);
}
4

4 回答 4

5

回答标题中的问题:不,您不能直接将 std::string 从托管代码编组为非托管代码。有关原因,请参阅另一个 SO 问题的答案。主要原因是 std::string 是模板而不是“真实”类型。

基本上,您需要编写一个小型非托管模块,它为 openCV 函数提供简单的包装,摆脱 STL 类型。使用您的示例函数,它可以很简单:

declspec(__dllexport) imread(char* c, int i) {
    string s = c;
    cv::imread(s, i);
}

至于字符串偏移的问题......尝试创建一个单独的项目,从一开始就使用“非托管”类型。将项目切换到托管并返回可能会导致项目设置混乱,产生不可预测的后果 - 至少,我已经两次遇到这样的坑......

于 2013-02-22T21:04:20.600 回答
1

您不应该(不能)在不同的模块(DLL)之间传递 std::string& ,除非您确定所有模块都以相同的方式编译(发布与调试等)。

例如:如果您在 release 中编译一个 DLL,而在 debug 中编译另一个 DLL - 那么 std::string 的内存布局可能会有所不同。其他编译器设置也可能影响内存布局。

试试这个 - 将下面的代码编译为发布与调试并运行它。在调试中,您在版本 28 中获得 32。

#include <iostream>
#include <string>

int main()
{
   std::cout << "sizeof(std::string) : " << sizeof(std::string) << std::endl;

   return 0;
}

我建议不要使用 std::string 跨越模块边界。

于 2013-02-28T22:11:37.933 回答
0

简短回答的,如果您对 DLL 和 C++/CLI 应用程序使用相同的编译器设置,则可以将 STL 字符串从 C++/CLI 应用程序传递给本机 C++ DLL。

代码

#include <msclr/marshal_cppstd.h> // header for marshal utilities

...

String^ path = "C:\\Users\\Don Reba\\Pictures\\Merlin 1D.jpg"; // Managed string
std::string s = msclr::interop::marshal_as<std::string>(path); // To stl string
cv::imread(s, CV_LOAD_IMAGE_GRAYSCALE);

有关详细信息,请参阅此页面:http: //msdn.microsoft.com/en-us/library/bb384865.aspx

于 2013-02-28T03:34:26.667 回答
0

问题是 Visual Studio 2010 默认为 C++ 和 C++/CLI 项目使用不同的工具集。这就是为什么 STL 类尽管设置相同但布局不同的原因。要解决此问题,请确保在 C++/CLI 项目中将配置属性/常规/平台工具集设置为 v100。

于 2013-03-02T01:15:54.900 回答