How to call an unmanaged C++ function with a std::vector::iterator as parameter from C#? -
How to call an unmanaged C++ function with a std::vector<>::iterator as parameter from C#? -
in unmanaged c++ have function i'm trying phone call c#. c++ function follows:
typedef std::vector<point> points; typedef std::back_insert_iterator<points> outputiterator; namespace mynamespace{ dllexport outputiterator convexhull(points::iterator first, points::iterator last, outputiterator result); }
when called c++, function used follows:
points points, result; points.push_back(point(0,0)); points.push_back(point(10,0)); points.push_back(point(10,10)); points.push_back(point(6,5)); points.push_back(point(4,1)); outputiterator resultiterator = std::back_inserter(result); mynamespace::convexhull( points.begin(), points.end(), resultiterator); std::cout << result.size() << " points on convex hull" << std::endl;
i've started writing c# code, i've no thought types should passing:
[dllimport("unmanagedcode.dll", entrypoint = "convexhull", callingconvention = callingconvention.stdcall)] public static extern ???<point> convex_hull_2(???<point> start, ???<point> last, ???<point> result);
the point construction in c# just:
struct point{ double x; double y; }
is case of passing array or list of point?
i have source c++ , can create changes function parameters; there different type of parameters easier phone call c#?
passing c++ types through p/invoke not going work. don't know layout , nil guarantees won't change. p/invoke meant inter-operating c.
one alternative utilize c++/cli instead of c++. won't portable (only supported vc++/windows), might easiest solution depending on how big c++ code already.
if want remain portable , utilize straight p/invoke c#, best bet refactor c++ convexhull
, provide new function callable c (and p/invoke).
// c-safe struct. struct results { point *points; std::size_t num_points; }; // store real results in vector, derive c-safe struct. struct resultsimpl : results { points storage; }; // convexhull has been refactored take pointers // instead of vector iterators. outputiterator convexhull(point const *first, point const *last, outputiterator result); // exported function callable c. // returns c-safe results, not resultsimpl. extern "c" dllexport results* convexhullc(point const *points, std::size_t num_points) { seek { std::unique_ptr<resultsimpl> r(new resultimpl); // fill in r->storage. convexhull(points, points + num_points, std::back_inserter(r->storage)); // fill in c-safe members. r->points = &r->storage[0]; r->numpoints = &r->storage.size(); homecoming r.release(); } catch(...) { // trap exceptions! homecoming 0; } } // needs called c# clean results. extern "c" dllexport void freeconvexhullc(results *r) { seek { delete (resultsimpl*)r; } catch(...) { // trap exceptions! } }
and c#:
[structlayout(layoutkind.sequential)] struct point { double x; double y; } [structlayout(layoutkind.sequential)] struct results { intptr points; intptr num_points; } [dllimport("unmanagedcode")] intptr convexhullc(point[] points, intptr pointcount); [dllimport("unmanagedcode")] void freeconvexhullc(intptr results); point[] convexhull(point[] points) { intptr pr = convexhull(points, new intptr(points.length)); if(pr == intptr.zero) { throw new exception("native error!"); } seek { results r = marshal.ptrtostructure(pr, typeof(results)); points = new point[checked((int)(long)r.num_points)]; for(int = 0; < points.length; ++i) { points[i] = marshal.ptrtostructure( r.points + marshal.sizeof(typeof(point)) * i, typeof(point)); } homecoming points; } { freeconvexhull(pr); } }
code not tested!
c# c++ pinvoke
Comments
Post a Comment