C# 通过静态变量从本机代码访问有状态托管对象 我有一个本地C++应用程序,我有一个C语言的DLL。我的C++应用程序需要访问C.Y.DLL的功能。为了做到这一点,我创建了一个混合模式C++ DLL。我的设计基本上是一样的。换言之: 我有一个混合的C++ DLL使用的C语言,它由一个本地C++应用程序使用。以下是我所做工作的简化版本:
C#DLLC# 通过静态变量从本机代码访问有状态托管对象 我有一个本地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
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 ;
}
问题
CPPDLL::Person
实例,那么它们都将在同一个csdl::Person^
实例上工作。因为本机类不能有托管数据成员,所以我不确定有什么明显的方法可以解决这个问题#include "Person.h"
int main ()
{
CPPDLL::Person person ("Billy", 5) ;
person.PrintPerson () ;
return 0 ;
}
有一个简单的方法来实现它,使每个代码的实例
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) ;
}