代码之家  ›  专栏  ›  技术社区  ›  Don Reba

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

  •  2
  • Don Reba  · 技术社区  · 13 年前

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

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

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

    非托管模块使用与OpenCV相同的CRT DLL,并且所有选项都设置为适用于正常OpenCV使用的值。为什么会有不同的 一串 布局我迷路了。

    示例代码:

    #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 回复  |  直到 13 年前
        1
  •  5
  •   Community Mohan Dere    9 年前

    回答标题中的问题:不,不能直接将std::string从托管代码封送到非托管代码。查看的答案 another SO question 原因。主要原因是std::string是一个模板,而不是“真正的”类型。

    基本上,您需要编写一个小型非托管模块,该模块为openCV函数提供简单的包装器,从而消除STL类型。对于您的示例函数,它可以简单到:

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

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

        2
  •  2
  •   Markus Schumann    13 年前

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

    例如:如果您在发布时编译一个DLL,在调试时编译另一个DLL——那么std::string的内存布局可能会有所不同。 其他编译器设置也可能影响内存布局。

    试试这个-将下面的代码编译为发行版与调试版,然后运行它。 在调试中,在relase 28中得到32。

    #include <iostream>
    #include <string>
    
    int main()
    {
       std::cout << "sizeof(std::string) : " << sizeof(std::string) << std::endl;
    
       return 0;
    }
    

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

        3
  •  0
  •   Chen    13 年前

    简短回答 : ,如果对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

        4
  •  0
  •   Don Reba    13 年前

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

    推荐文章