Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
反转pinvoke,调用C#object';从本机C/C++;不带CLI/CLR的DLL 我想制作一个C++类,它封装了一个在Win窗体应用程序中存在的托管对象的引用,以便它可以从两侧(C和C++)进行操作。 这个对象将从C++异步访问。为此,我希望在本机代码中存储对该托管对象的引用。我知道GC可以收集它,所以我读到应该在托管代码中的某个地方引用它来防止这种情况_C#_C++_Interop_Pinvoke - Fatal编程技术网

反转pinvoke,调用C#object';从本机C/C++;不带CLI/CLR的DLL 我想制作一个C++类,它封装了一个在Win窗体应用程序中存在的托管对象的引用,以便它可以从两侧(C和C++)进行操作。 这个对象将从C++异步访问。为此,我希望在本机代码中存储对该托管对象的引用。我知道GC可以收集它,所以我读到应该在托管代码中的某个地方引用它来防止这种情况

反转pinvoke,调用C#object';从本机C/C++;不带CLI/CLR的DLL 我想制作一个C++类,它封装了一个在Win窗体应用程序中存在的托管对象的引用,以便它可以从两侧(C和C++)进行操作。 这个对象将从C++异步访问。为此,我希望在本机代码中存储对该托管对象的引用。我知道GC可以收集它,所以我读到应该在托管代码中的某个地方引用它来防止这种情况,c#,c++,interop,pinvoke,C#,C++,Interop,Pinvoke,我的问题是:是否可以在本机DLL中存储对托管对象的引用(不使用CLI/CLR内容)并使用它异步调用方法?如果是,传递对象的语法是什么?还有那个托管对象的方法呢?我是否还需要在本机代码中存储对它们的引用 谢谢。:) 我写这篇文章是希望大卫·赫弗南能纠正我的错误并教我一些东西:-) 正如我在评论中所写: 我的问题是:是否可以在本机DLL中存储对托管对象的引用(不使用CLI/CLR内容) 在某种程度上,您必须告诉CLR您不希望收集对象。您可以在静态属性中保留引用,您可以直接使用GCHandle将其固定

我的问题是:是否可以在本机DLL中存储对托管对象的引用(不使用CLI/CLR内容)并使用它异步调用方法?如果是,传递对象的语法是什么?还有那个托管对象的方法呢?我是否还需要在本机代码中存储对它们的引用


谢谢。:)

我写这篇文章是希望大卫·赫弗南能纠正我的错误并教我一些东西:-)

正如我在评论中所写:

我的问题是:是否可以在本机DLL中存储对托管对象的引用(不使用CLI/CLR内容)

在某种程度上,您必须告诉CLR您不希望收集对象。您可以在静态属性中保留引用,您可以直接使用
GCHandle
将其固定,您可以使用COM,但事实是您必须告诉CLR

使用COM对象很复杂(至少对我来说:-)

我要做的是:

给出了<代码> MyClass < />代码,对象创建了C*A侧,用<代码> DoSomething < /C> >方法,我想同时使用C和C++边。

public class MyClass
{
    public string Name;
    public string Surname;

    public bool DoSomething(int value1, int value2)
    {
        return Name.Length == value1 || Surname.Length == value2;
    }
}
我将创建一个
MyProxyClass
,如下所示:

public class MyProxyClass
{
    private delegate void FreeMeDelegate();

    [return:MarshalAs(UnmanagedType.I1)]
    private delegate bool DoSomethingDelegate(int value1, int value2);

    private GCHandle Handle;
    private DoSomethingDelegate DoSomething { get; set; }

    // You pass this function pointer to C++. Its signature is:
    // bool(__stdcall *DoSomething)(int32_t, int32_t)
    public IntPtr DoSomethingPtr { get; private set; }

    private FreeMeDelegate FreeMe { get; set; }

    // You have to pass this function too to C++. C++ code must use it
    // to free MyProxyClass. Its signature is:
    // void (__stdcall *FreeMe)(void)
    public IntPtr FreeMePtr { get; private set; }

    public void FreeMeImpl()
    {
        if (Handle.IsAllocated)
        {
            Handle.Free();
            DoSomething = null;
            DoSomethingPtr = IntPtr.Zero;
            FreeMe = null;
            FreeMePtr = IntPtr.Zero;
        }
    }

    public MyProxyClass(MyClass obj)
    {
        Handle = GCHandle.Alloc(this, GCHandleType.Normal);

        // This will implicitly create a reference to obj. GC can't
        // collect MyProxyClass because we have a GCHandle on it,
        // and can't collect obj because there is a delegate that
        // has a reference on it.
        DoSomething = obj.DoSomething;
        DoSomethingPtr = Marshal.GetFunctionPointerForDelegate(DoSomething);

        FreeMe = FreeMeImpl;
        FreeMePtr = Marshal.GetFunctionPointerForDelegate(FreeMe);
    }
}
该类在创建时会自动停止GC对其进行收集。然后创建一些<代码> ItpTrt/Cux>委托给方法<代码> DoSomething < /C>和到<代码> FreeMe < /C>方法,C++代码将需要使用它来释放它。 现在,C侧:


COM是实现这一点的最干净的方法我的问题是:在某种程度上,是否可以在本机DLL中存储对托管对象的引用(不使用CLI/CLR内容),您必须告诉CLR您不希望收集对象。您可以在静态属性中保留引用,您可以直接用GCHandle来直接引用它,但您可以使用COM,但事实是您必须告诉CLR。CLR不是某种C++扩展吗?这是C#的一部分吗?没有CLI/CLR,我就意味着我想使用标准的C++,而不是MS的扩展C++。@ Viru721不,CLR是公共语言运行时,.NET虚拟机。CLR的两个重要部分是从IL代码编译到机器代码的部分和垃圾收集器,我对此一无所知。在我看来,我会使用COM、C++/CLI混合模式或非托管Dexports。
MyClass myclass = ...; // you instance of myclass

var proxy = new MyProxyClass(myclass);

// Now you pass these to C++
//proxy.DoSomethingPtr;
//proxy.FreeMePtr;