Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
709 views
in Technique[技术] by (71.8m points)

.net - How can I marshall a vector<int> from a C++ dll to a C# application?

I have a C++ function that produces a list of rectangles that are interesting. I want to be able to get that list out of the C++ library and back into the C# application that is calling it.

So far, I'm encoding the rectangles like so:

struct ImagePatch{ 
   int xmin, xmax, ymin, ymax;
}

and then encoding some vectors:

void MyFunc(..., std::vector<int>& rectanglePoints){
   std::vector<ImagePatch> patches; //this is filled with rectangles
   for(i = 0; i < patches.size(); i++){
       rectanglePoints.push_back(patches[i].xmin);
       rectanglePoints.push_back(patches[i].xmax);
       rectanglePoints.push_back(patches[i].ymin);
       rectanglePoints.push_back(patches[i].ymax);
   }
}

The header for interacting with C# looks like (and works for a bunch of other functions):

extern "C" {
    __declspec(dllexport) void __cdecl MyFunc(..., std::vector<int>& rectanglePoints);
}

Are there some keywords or other things I can do to get that set of rectangles out? I found this article for marshalling objects in C#, but it seems way too complicated and way too underexplained. Is a vector of integers the right way to do this, or is there some other trick or approach?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The STL is a C++ specific library, so you cant directly get it across as one object to C#.

The one thing that is guaranteed about std::vector is that &v[0] points to the first element and all the elements lie linearly in memory (in other words, its just like a C array in terms of memory layout)

So marshal as array of int... which shouldn't be hard - There are lot of examples on the web.

Added

Assuming you only pass the data from C++ to C# :

C# cannot handle a C++ vector object, so do not try passing it by reference : Instead your C++ code must return a pointer to an array of ints...

If you are not going to be using this function from multiple threads, you can use static storage :

int *getRects(bool bClear)
{
    static vector<int> v; // This variable persists across invocations
    if(bClear)
    {
        v.swap(vector<int>());
    }
    else
    {
        v.clear();
        // Fill v with data as you wish
    }

    return v.size() ? &v[0] : NULL;
}

call getRects(true) if the returned data is significant in size, so you release the memory in v.

For simplicity, instead of passing out the size of the vector data too, just put a sentinel value at the end (like say -1) so the C# code can detect where the data ends.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...