Question

I'd like to know a way how to marshal 2 Classes that I made in C++ in C# language. (a tutorial link would be perfect, I tried to google this for myself, but my english knowledge is not that advance, to search for the right thing. I am new to marshaling from C++ to C#)

Well basically what I have is something like this:

C++

EXPORT_API CarClass* DLL_AddCar();
EXPORT_API CarWheel* DLL_AddWheel();
EXPORT_API void DLL_GiveWheelToCar(CarClass* car,CarWheel* wheel);

C#

public class Car
{       
    #region Members     
    private IntPtr nativeCarObject; 
    #endregion Members

    public Car()
    {           
        this.nativeCarObject = Sim.DLL_AddCar();

    }

    // ---> this part is not working
    //#region Wrapper methods           
    //public void GiveWheel(Wheel myWheel){Sim.DLL_GiveWheelToCar(this.nativeCarObject,myWheel);}
    //#endregion Wrapper methods
}

public class Wheel
{       
    #region Members     
    private IntPtr nativeCarObject; 
    #endregion Members

    public Wheel()
    {           
        this.nativeCarObject = Sim.DLL_AddWheel();

    }
}   

internal class Sim
{
    public const string pluginName = "MyDLL";   

    #region PInvokes
    [DllImport(pluginName)] public static extern IntPtr DLL_AddCar();
    [DllImport(pluginName)] public static extern IntPtr DLL_AddWheel();
    [DllImport(pluginName)] public static extern void DLL_GiveWheelToCar(IntPtr car,IntPtr wheel);
    #endregion PInvokes 
}

Now My question is where would I use "DLL_GiveWheelToCar" ? The method I tryed is commented out, because it didnt work, is it a logic error or should I change the way I'm marshaling?

Thanks for advice.

Was it helpful?

Solution

public void GiveWheel(Wheel myWheel){
    Sim.DLL_GiveWheelToCar(this.nativeCarObject, myWheel);
}

Here you are passing myWheel which is of type Wheel to a function that expects an IntPtr. You need to pass the private field of the Wheel class that is currently (mis)named nativeCarObject.

Other points:

  1. As I hinted above, the nativeCarObject member of Wheel should be renamed as nativeWheelObject.
  2. The DLL looks like it uses the cdecl calling convention. You should specify that in your p/invoke declarations.
  3. It looks like you code leaks the objects that the DLL supplies. I suspect you need to supply some tidy up helpers.

The code might look like something this:

public class Car
{
    public readonly IntPtr nativeCarObject = Sim.DLL_AddCar();

    public void GiveWheel(Wheel myWheel)
    {
        Sim.DLL_GiveWheelToCar(this.nativeCarObject, myWheel.nativeWheelObject);
    }    
}

public class Wheel
{
    public readonly IntPtr nativeWheelObject = Sim.DLL_AddWheel();
}

internal class Sim
{
    public const string pluginName = "MyDLL";

    [DllImport(pluginName, CallingConvention=CallingConvention.Cdecl)]
    public static extern IntPtr DLL_AddCar();
    [DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr DLL_AddWheel();
    [DllImport(pluginName, CallingConvention = CallingConvention.Cdecl)]
    public static extern void DLL_GiveWheelToCar(IntPtr car, IntPtr wheel);
}

This code is still leaking those objects. I'll let you sort that out.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top