如何将 ATL com 对象从 C++ 传递到 C#
How to Pass an ATL com object from c++ to c#
我使用 ATl 创建了一个名为“Comptes”的 com 对象,它具有名称、用户名等属性。这是 atl 项目的 idl 文件
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(15297371-6D05-4466-B80D-26207555CD28),
dual,
nonextensible,
pointer_default(unique)
]
interface Icompte : IDispatch{
[propget, id(1)] HRESULT name([out, retval] BSTR* pVal);
[propput, id(1)] HRESULT name([in] BSTR newVal);
[propget, id(2)] HRESULT sername([out, retval] BSTR* pVal);
[propput, id(2)] HRESULT sername([in] BSTR newVal);
[propget, id(3)] HRESULT email([out, retval] BSTR* pVal);
[propput, id(3)] HRESULT email([in] BSTR newVal);
[propget, id(4)] HRESULT phone([out, retval] BSTR* pVal);
[propput, id(4)] HRESULT phone([in] BSTR newVal);
};
[
uuid(73A9DD4C-CE2D-4419-9F95-4A84C4E3B271),
version(1.0),
]
library ATLOBJECTSLib
{
importlib("stdole2.tlb");
[
uuid(1199A9AD-8AF7-4A25-A10B-DD06FB294B2E)
]
coclass compte
{
[default] interface Icompte;
};
};
我已经在 c++ mfc 项目中包含了头文件和 cpp 文件,并且能够确定 com 对象,现在在 mfc 项目中我正在向 c# 项目发送数据(只是简单的字符串)
这是 MFC 部分:
void CmfcappDlg::OnBnClickedCreateacountbutt()
{
CoInitializeEx(nullptr, COINIT::COINIT_MULTITHREADED);
Icompte* pcompte;
HRESULT hr = CoCreateInstance(CLSID_compte,nullptr,CLSCTX_INPROC_SERVER,IID_Icompte,(LPVOID*)&pcompte);
if (SUCCEEDED(hr))
{
namectrl.GetWindowText(name);
sernamectrl.GetWindowText(sername);
emailctrl.GetWindowText(email);
phonectrl.GetWindowText(phone);
pcompte->put_name(name.AllocSysString());
pcompte->put_sername(sername.AllocSysString());
pcompte->put_phone(phone.AllocSysString());
pcompte->put_phone(email.AllocSysString());
//Managed::showcswindow(name, sername);
}
CoUninitialize();
}
现在我可以用这个 class 将数据发送到 c# 部分:
#include "stdafx.h"
#include "Managed.h"
#using <System.dll>
using namespace System;
using namespace ::gettingdatafromc;
void Managed::showcswindow(CString name,CString sername)
{
services::showwindow(gcnew String(name), gcnew String(sername));
}
并在 c# 项目中接收它 class :
namespace gettingdatafromc
{
public static class services
{
public static void showwindow(string name, string sername)
{
}
}
}
一切正常,除了我想通过将 com 对象作为参数传递给 showwindow 方法而不是将简单的字符串传递给 c# 项目来发送 com 对象,这甚至是可移植的,
尝试将原始 IUnkown*
指针传递给 C#,然后使用 Marshal.GetObjectForIUnknown
将 IntPtr
转换为 object
,然后将此对象转换为 Icompte
。您需要将对相应类型库的引用添加到 C# 项目中才能执行此类转换。
感谢您的友好回复,所以我在应用程序中遵循了您的指南,我使用了一种新的 showwindow2 方法:
CoInitializeEx(nullptr, COINIT::COINIT_MULTITHREADED);
Icompte* pcompte;
HRESULT hr = CoCreateInstance(CLSID_compte,nullptr,CLSCTX_INPROC_SERVER,IID_Icompte,(LPVOID*)&pcompte);
if (SUCCEEDED(hr))
{
namectrl.GetWindowText(name);
sernamectrl.GetWindowText(sername);
emailctrl.GetWindowText(email);
phonectrl.GetWindowText(phone);
pcompte->put_name(name.AllocSysString());
pcompte->put_sername(sername.AllocSysString());
pcompte->put_phone(phone.AllocSysString());
pcompte->put_phone(email.AllocSysString());
//Managed::showcswindow(name, sername);
Managed::showcswindow2(pcompte);
}
CoUninitialize();
wich 在 managed.cpp 中找到,我将 Iunknow 传递给了 csahrp 方法):
void Managed::showcswindow2(IUnknown* p)
{
services::showwindow2((IntPtr)p);
}
在 csharp 代码中:
public static void showwindow2(IntPtr p)
{
Icompte c = (Icompte)Marshal.GetObjectForIUnknown(p);
string b = c.name;
}
dll 已经注册并被引用包含;
现在的问题是csharp代码中对象的属性为空,字符串b为null。
我使用 ATl 创建了一个名为“Comptes”的 com 对象,它具有名称、用户名等属性。这是 atl 项目的 idl 文件
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(15297371-6D05-4466-B80D-26207555CD28),
dual,
nonextensible,
pointer_default(unique)
]
interface Icompte : IDispatch{
[propget, id(1)] HRESULT name([out, retval] BSTR* pVal);
[propput, id(1)] HRESULT name([in] BSTR newVal);
[propget, id(2)] HRESULT sername([out, retval] BSTR* pVal);
[propput, id(2)] HRESULT sername([in] BSTR newVal);
[propget, id(3)] HRESULT email([out, retval] BSTR* pVal);
[propput, id(3)] HRESULT email([in] BSTR newVal);
[propget, id(4)] HRESULT phone([out, retval] BSTR* pVal);
[propput, id(4)] HRESULT phone([in] BSTR newVal);
};
[
uuid(73A9DD4C-CE2D-4419-9F95-4A84C4E3B271),
version(1.0),
]
library ATLOBJECTSLib
{
importlib("stdole2.tlb");
[
uuid(1199A9AD-8AF7-4A25-A10B-DD06FB294B2E)
]
coclass compte
{
[default] interface Icompte;
};
};
我已经在 c++ mfc 项目中包含了头文件和 cpp 文件,并且能够确定 com 对象,现在在 mfc 项目中我正在向 c# 项目发送数据(只是简单的字符串) 这是 MFC 部分:
void CmfcappDlg::OnBnClickedCreateacountbutt()
{
CoInitializeEx(nullptr, COINIT::COINIT_MULTITHREADED);
Icompte* pcompte;
HRESULT hr = CoCreateInstance(CLSID_compte,nullptr,CLSCTX_INPROC_SERVER,IID_Icompte,(LPVOID*)&pcompte);
if (SUCCEEDED(hr))
{
namectrl.GetWindowText(name);
sernamectrl.GetWindowText(sername);
emailctrl.GetWindowText(email);
phonectrl.GetWindowText(phone);
pcompte->put_name(name.AllocSysString());
pcompte->put_sername(sername.AllocSysString());
pcompte->put_phone(phone.AllocSysString());
pcompte->put_phone(email.AllocSysString());
//Managed::showcswindow(name, sername);
}
CoUninitialize();
}
现在我可以用这个 class 将数据发送到 c# 部分:
#include "stdafx.h"
#include "Managed.h"
#using <System.dll>
using namespace System;
using namespace ::gettingdatafromc;
void Managed::showcswindow(CString name,CString sername)
{
services::showwindow(gcnew String(name), gcnew String(sername));
}
并在 c# 项目中接收它 class :
namespace gettingdatafromc
{
public static class services
{
public static void showwindow(string name, string sername)
{
}
}
}
一切正常,除了我想通过将 com 对象作为参数传递给 showwindow 方法而不是将简单的字符串传递给 c# 项目来发送 com 对象,这甚至是可移植的,
尝试将原始 IUnkown*
指针传递给 C#,然后使用 Marshal.GetObjectForIUnknown
将 IntPtr
转换为 object
,然后将此对象转换为 Icompte
。您需要将对相应类型库的引用添加到 C# 项目中才能执行此类转换。
感谢您的友好回复,所以我在应用程序中遵循了您的指南,我使用了一种新的 showwindow2 方法:
CoInitializeEx(nullptr, COINIT::COINIT_MULTITHREADED);
Icompte* pcompte;
HRESULT hr = CoCreateInstance(CLSID_compte,nullptr,CLSCTX_INPROC_SERVER,IID_Icompte,(LPVOID*)&pcompte);
if (SUCCEEDED(hr))
{
namectrl.GetWindowText(name);
sernamectrl.GetWindowText(sername);
emailctrl.GetWindowText(email);
phonectrl.GetWindowText(phone);
pcompte->put_name(name.AllocSysString());
pcompte->put_sername(sername.AllocSysString());
pcompte->put_phone(phone.AllocSysString());
pcompte->put_phone(email.AllocSysString());
//Managed::showcswindow(name, sername);
Managed::showcswindow2(pcompte);
}
CoUninitialize();
wich 在 managed.cpp 中找到,我将 Iunknow 传递给了 csahrp 方法):
void Managed::showcswindow2(IUnknown* p)
{
services::showwindow2((IntPtr)p);
}
在 csharp 代码中:
public static void showwindow2(IntPtr p)
{
Icompte c = (Icompte)Marshal.GetObjectForIUnknown(p);
string b = c.name;
}
dll 已经注册并被引用包含;
现在的问题是csharp代码中对象的属性为空,字符串b为null。