gpt4 book ai didi

c# - 通过静态变量从 native 代码访问有状态托管对象

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:20:36 24 4
gpt4 key购买 nike

我有一个 native C++ 应用程序和一个 C# DLL。我的 native C++ 应用程序需要访问 C# DLL 的功能。为此,我创建了一个混合模式的 C++ DLL。我的设计基本上是 same as this .换句话说:

我有一个由混合 C++ DLL 使用的 C# DLL,它由 native C++ 应用程序使用。这是我正在做的事情的简化版本:

C# 动态链接库

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++ 动态链接库

Person.h:适合原生应用的头文件。

#include <string>

namespace CPPDLL
{
class __declspec(dllexport) Person
{
public:
Person () ;
Person (const std::string &name, int age);
void PrintPerson () const ;
};
}

Person.cpp:混合代码实现。 注意静态变量 person

#include "Person.h"

namespace CPPDLL
{
ref class Wrap
{
public:
static CSDLL::Person ^person = gcnew CSDLL::Person () ;
};

Person::Person ()
{
}

Person::Person (const std::string &name, int age)
{
System::String ^csName = gcnew System::String (name.data ()) ;
Wrap::person = gcnew CSDLL::Person (csName, age) ;
}

void Person::PrintPerson () const
{
System::Console::WriteLine (Wrap::person) ;
}
}

示例 native C++ 应用程序

#include "Person.h"

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

return 0 ;
}

问题

  1. 我必须将 C++ DLL 中的 native API header 公开给 C++ 应用程序。
  2. native 类不能将托管对象作为成员变量。
  3. 目前,如果 native 应用程序创建了多个 CPPDLL::Person 实例,那么它们都将在同一个 CSDLL::Person^ 实例上工作。因为 native 类不能有托管数据成员,所以我不确定有什么明显的方法可以解决这个问题。

问题

是否有一种简单/明显的方法可以使 CPPDLL::Person 的每个实例都与它自己的 CSDLL::Person^ 拷贝一起工作?

最佳答案

问题是在混合 C++ 中为每个 CPPDLL::Person 实例创建一个 C# CSDLL::Person 实例。作为原生类中的CPPDLL::Person,它不能直接持有被管理对象的引用,但是你可以通过GCHandle来实现。 ,它提供了一种从非托管内存访问托管对象的方法。

您可以这样更改代码:

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

关于c# - 通过静态变量从 native 代码访问有状态托管对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26933210/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com