3

I have c++ unmanaged code that i want to access from c#. So i followed some tutorials and i build a dll for my project (only one class btw). Now i want to use it from c#, and i'm using p/invoke as follows.

my question is: is it possible to marshall my windows point so i can pass it as a vector into my c++ code? i can change all the code (except the qwindows point, but i can make my own point). IS there a solution where i dont have to create a c wrapper? i was following this question: How to call an unmanaged C++ function with a std::vector<>::iterator as parameter from C#?

many thanks1 ps, i found a "solution" but i cant view it http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_21461195.html

c#

using Point = System.Windows.Point;

class CPlusPlusWrapper
{

    [DllImport("EmotionsDLL.dll", EntryPoint = "calibrate_to_file")]
    static extern int calibrate_to_file(vector<points> pontos);//marshall here

    [DllImport("EmotionsDLL.dll", EntryPoint = "calibration_neutral")]
    static extern int calibration_neutral();
    /// <summary>
    /// wraps c++ project into c#
    /// </summary>

    public void calibrate_to_file() { 

}

dll header

namespace EMOTIONSDLL
{
    struct points{
        double x;
        double y;
        double z;
    };

    #define db at<double>

    class DLLDIR EMOTIONS
    {
    public:

        EMOTIONS();

        CvERTrees *  Rtree ;


        vector<points> mapear_kinect_porto(vector<points> pontos);

        void calibrate_to_file(vector<points> pontos);

        int calibration_neutral();

        int EmotionsRecognition();
    };
}
Community
  • 1
  • 1
virgula24
  • 523
  • 5
  • 23

2 Answers2

4

You could marshal a C# array as a C++ std::vector, but it would be very complicated and is simply not a good idea because the layout and implementation of std::vector is not guaranteed to be the same between compiler versions.

Instead you should change the parameter into a pointer to an array, and add a parameter specifying the length of the array:

int calibrate_to_file(points* pontos, int length);

And in C# declare the method as taking an array and apply the MarshalAs(UnmanagedType.LPArray) attribute:

static extern int calibrate_to_file([MarshalAs(UnmanagedType.LPArray)]] Point[] pontos, int length);

Note also that your C++ point structure is not compatible with System.Windows.Point. The latter doesn't have a z member.

But a bigger issue with your code is that you can't really expect to DLL-import an instance method and be able to call it just like that. An instance method needs an instance of its class, and there's no easy way to create an instance of a non-COM C++ class from C# (and is also not a good idea). Therefore, you should turn this into a COM class, or create a C++/CLI wrapper for it.

user1610015
  • 6,561
  • 2
  • 15
  • 18
  • I tried some COM tutorials but it just got too messy. can u point me to a good and easy to follow tutorial con cli wrapper, i dont now that much about c++ or c#, i came from java. im also gonna try the sugestion nefarion gave! – virgula24 Mar 19 '13 at 03:03
  • @virgula24 C++/CLI is a superset of C++, it's like C++ with some of the features of C#, so it's easy to learn if you know C++ and C#. You can learn it by looking at some samples, here: http://msdn.microsoft.com/library/a9e2eysz(en-us,vs.80).aspx – user1610015 Mar 19 '13 at 11:20
1

I think you should just pass Arrays of your types and then convert them to vector<T>'s or List's in the relative functions.

What it could also be is the fact you referenced a static externINTcalibrate_to_file() and in C++ it is VOIDcalibrate_to_file()

UPDATE: And I think you are missing the DLLEXPORT tags on your functions?

frogatto
  • 28,539
  • 11
  • 83
  • 129
Nefarion
  • 872
  • 2
  • 8
  • 28