Marshal 2 IntPtr 在同一个函数中?

Posted

技术标签:

【中文标题】Marshal 2 IntPtr 在同一个函数中?【英文标题】:Marshal 2 IntPtr's in the same function? 【发布时间】:2014-01-17 13:45:38 【问题描述】:

我想知道如何用 C# 语言编组我在 C++ 中创建的 2 个类。 (一个教程链接会很完美,我试着自己用谷歌搜索,但我的英语知识不是那么先进,要搜索正确的东西。我是从 C++ 编组到 C# 的新手)

嗯,基本上我所拥有的是这样的:

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 

现在我的问题是我将在哪里使用 "DLL_GiveWheelToCar" ? 我尝试的方法被注释掉了,因为它不起作用,是逻辑错误还是我应该改变我编组的方式?

感谢您的建议。

【问题讨论】:

【参考方案1】:
public void GiveWheel(Wheel myWheel)
    Sim.DLL_GiveWheelToCar(this.nativeCarObject, myWheel);

在这里,您将myWheel 类型为Wheel 传递给需要IntPtr 的函数。您需要传递当前(错误)命名为 nativeCarObjectWheel 类的私有字段。

其他要点:

    正如我上面所暗示的,Wheel 的成员 nativeCarObject 应重命名为 nativeWheelObject。 DLL 看起来使用cdecl 调用约定。您应该在 p/invoke 声明中指定这一点。 您的代码似乎泄露了 DLL 提供的对象。我怀疑您需要提供一些整理帮手。

代码可能如下所示:

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);

此代码仍在泄漏这些对象。我会让你解决这个问题。

【讨论】:

谢谢!我做了改变。关于对象本身,我创建了一个 GetObject 方法,该方法返回它的 IntPtr。是否有可能以某种方式从 IntPtr 派生? 我认为从IntPtr派生没有意义。

以上是关于Marshal 2 IntPtr 在同一个函数中?的主要内容,如果未能解决你的问题,请参考以下文章

知道内存中一个图片的指针IntPtr大小,转换成图片显示

如何将IntPtr类型转为Image类型

我用C#,上一步函数返回了一个IntPtr型的图片指针,我已知图片的长、宽,如何转换成image类。

如何在 C# 中获取 IntPtr 指针的属性

内存中一个图片的指针IntPtr

c# 调用c dll void 指针类型转化问题