将STL字符串从C ++ / CLI应用程序传递到C ++ DLL

时间:2013-02-20 03:02:49

标签: c++ opencv c++-cli

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

感兴趣的功能是cv::imread(std::string&, int)。简单地从托管模块调用它根本不起作用,产生<无效指针>在接收端。我有点期待它。毕竟,托管代码有自己的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 个答案:

答案 0 :(得分:5)

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

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

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

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

答案 1 :(得分:0)

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

<强>代码

#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

答案 2 :(得分:0)

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

例如:如果你在发行版中编译一个DLL而另一个作为调试编译 - 那么std :: string的内存布局可能会有所不同。 其他编译器设置也可能会影响内存布局。

试试这个 - 将下面的代码编译为release vs. debug并运行它。 在调试中,你得到32 in relase 28。

#include <iostream>
#include <string>

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

   return 0;
}

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

答案 3 :(得分:0)

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