Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/256.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
C# 通过静态变量从本机代码访问有状态托管对象 我有一个本地C++应用程序,我有一个C语言的DLL。我的C++应用程序需要访问C.Y.DLL的功能。为了做到这一点,我创建了一个混合模式C++ DLL。我的设计基本上是一样的。换言之: 我有一个混合的C++ DLL使用的C语言,它由一个本地C++应用程序使用。以下是我所做工作的简化版本:_C#_C++ - Fatal编程技术网

C# 通过静态变量从本机代码访问有状态托管对象 我有一个本地C++应用程序,我有一个C语言的DLL。我的C++应用程序需要访问C.Y.DLL的功能。为了做到这一点,我创建了一个混合模式C++ DLL。我的设计基本上是一样的。换言之: 我有一个混合的C++ DLL使用的C语言,它由一个本地C++应用程序使用。以下是我所做工作的简化版本:

C# 通过静态变量从本机代码访问有状态托管对象 我有一个本地C++应用程序,我有一个C语言的DLL。我的C++应用程序需要访问C.Y.DLL的功能。为了做到这一点,我创建了一个混合模式C++ DLL。我的设计基本上是一样的。换言之: 我有一个混合的C++ DLL使用的C语言,它由一个本地C++应用程序使用。以下是我所做工作的简化版本:,c#,c++,C#,C++,C#DLL using System; namespace CSDLL { public class Person { public string Name { get; set; } public int Age { get; set; } public Person() : this("Bob", 30) { } public Person(String name, Int3

C#DLL

using System;

namespace CSDLL
{
    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public Person() : this("Bob", 30)
        {
        }

        public Person(String name, Int32 age)
        {
            Name = name;
            Age = age;
        }

        public override string ToString()
        {
            return String.Format("<Person Name=\"{0}\" Age=\"{1}\"/>", Name, Age);
        }
    }
}

<强>示例本机C++应用<强/> /P>

#include "Person.h"

int main ()
{
    CPPDLL::Person person ("Billy", 5) ;
    person.PrintPerson () ;

    return 0 ;
}
问题

我必须将一个本地API头从C++ DLL公开到C++应用程序。
  • 本机类不能将托管对象作为成员变量
  • 当前,如果本机应用程序创建了多个
    CPPDLL::Person
    实例,那么它们都将在同一个
    csdl::Person^
    实例上工作。因为本机类不能有托管数据成员,所以我不确定有什么明显的方法可以解决这个问题
  • 问题

    #include "Person.h"
    
    int main ()
    {
        CPPDLL::Person person ("Billy", 5) ;
        person.PrintPerson () ;
    
        return 0 ;
    }
    

    有一个简单的方法来实现它,使每个代码的实例cppdL::人< /COD>与它的自己的副本<代码> CSDL::人^ < /COD> > /p> < p>问题是为每个CPPdL::在混合C++中创建一个C实例:作为本机类中的CPPDLL::Person,它不能直接保存托管对象的引用,但您可以通过它来实现,它提供了一种从非托管内存访问托管对象的方法

    您可以这样更改代码:

    在CPPDLL::Person的声明中,添加一个整数成员变量,该变量用作指向托管对象的指针

        namespace CPPDLL
    {
        class __declspec(dllexport) Person
        {
        private:
            int m_personPtr;
        public:
            Person () ;
            Person (const std::string &name, int age);
            void PrintPerson () const ;
        };
    }
    
    CPPDLL::Persion的实现如下:

    ref class Wrap 
        {
        public: 
            static int CreatePerson(const std::string &name, int age)
            {
                System::String ^csName = gcnew System::String (name.data ()) ;
                CSDLL::Person ^person = gcnew CSDLL::Person (csName, age) ;
    
                //pin the manage object and return the handle as int values
                GCHandle^ handle = GCHandle::Alloc(person, GCHandleType.Pinned);
                IntPtr^ ptr = handle->AddrOfPinnedObject();
                return ptr->ToInt32();
            }
    
            static void Release(int p)
            {
                //unpin the manage object and release it.
                GCHandle^ handle = GCHandle::FromIntPtr(gcnew IntPtr(p));
                if (handle != nullptr)
                    handle->Free();
            }
        };
    
        Person::Person ()
            :m_personPtr(0)
        {
        }
    
        Person::Person (const std::string &name, int age)
        {
            m_personPtr = Wrap::CreatePerson(name, age);
        }
    
        Person::~Person ()      
        {
            Wrap::Release(m_personPtr);
        }
    
        void Person::PrintPerson () const
        {
            System::Console::WriteLine (Wrap::person) ;
        }
    

    哇,这看起来很棒。只是几个问题。在
    CreatePerson()
    内部,
    Alloc(obj
    应该是
    Alloc(person
    )吗?我所要做的就是将句柄转换为
    csdl::person
    对象,调用
    GetType()
    ,对吗?@jliv902,是的,应该是人,你不需要卡斯特。我刚刚意识到这个解决方案不起作用。我收到一个错误,说“对象包含非原始或不可删除的数据。”当我尝试这行时:
    GCHandle^handle=GCHandle::Alloc(person,GCHandleType.pinted);
    。我需要仔细阅读这个问题。@jliv902将[StructLayout(LayoutKind.Sequential)]添加到C#Person的定义中class@jliv902本博客详细介绍了以下内容:
    ref class Wrap 
        {
        public: 
            static int CreatePerson(const std::string &name, int age)
            {
                System::String ^csName = gcnew System::String (name.data ()) ;
                CSDLL::Person ^person = gcnew CSDLL::Person (csName, age) ;
    
                //pin the manage object and return the handle as int values
                GCHandle^ handle = GCHandle::Alloc(person, GCHandleType.Pinned);
                IntPtr^ ptr = handle->AddrOfPinnedObject();
                return ptr->ToInt32();
            }
    
            static void Release(int p)
            {
                //unpin the manage object and release it.
                GCHandle^ handle = GCHandle::FromIntPtr(gcnew IntPtr(p));
                if (handle != nullptr)
                    handle->Free();
            }
        };
    
        Person::Person ()
            :m_personPtr(0)
        {
        }
    
        Person::Person (const std::string &name, int age)
        {
            m_personPtr = Wrap::CreatePerson(name, age);
        }
    
        Person::~Person ()      
        {
            Wrap::Release(m_personPtr);
        }
    
        void Person::PrintPerson () const
        {
            System::Console::WriteLine (Wrap::person) ;
        }