[英]Passing a pointer to COM interface pointer from managed c++ to .NET C#
我有一個用非托管 C++ 編寫的 COM Dll,它公開了一個 com 接口。 idl 的簡單示例如下所示:
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(A806FAED-FCE2-4F1B-AE67-4B36D398508E),
dual,
nonextensible,
pointer_default(unique)
]
interface IObjectToPass : IDispatch{
[propget, id(1)] HRESULT Name([out, retval] BSTR* pVal);
[propput, id(1)] HRESULT Name([in] BSTR newVal);
};
[
uuid(B99537C0-BEBC-4670-A77E-06AB5350DC23),
version(1.0),
]
library {
importlib("stdole2.tlb");
[
uuid(FB7C7D08-0E38-40D2-A160-0FC8AE76C3CF)
]
coclass ObjectToPass
{
[default] interface IObjectToPass;
};
};
所以 IObjectToPass 接口是暴露的接口。 現在我已經在 C# 中實現了一個 .NET 庫(ObjectConsumer),它通過一個由 tlbimp 這個 COM 對象創建的互操作導入,所以我可以使用 IObjectToPass 接口。 下面是這個庫的示例代碼:
using Interop.ComTest;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;ComTestLib
using System.Threading.Tasks;
namespace ObjectConsumer
{
public class Consumer
{
public void PassObject(IObjectToPass passobj)
{
string str = passobj.Name;
}
}
}
c++ 和 c# 模塊編譯都沒有問題
現在我已經在 C++ 中創建了一個簡單的控制台應用程序,它支持 CLR,它通過 import 和 Consumer 添加對控制台應用程序項目的引用來導入 ComTestLib。 我的目標是在我的控制台應用程序中獲取 ObjectToPass 的一個實例,並傳遞給調用公共方法 PassObject 的消費者,如下所示
#include "stdafx.h"
#import "..\Debug\ComTest.tlb" no_namespace, raw_interfaces_only
int main()
{
CoInitialize(NULL);
IObjectToPassPtr obj;
HRESULT hr = obj.CreateInstance(__uuidof(IObjectToPass) );
ObjectConsumer::Consumer^ consumer = gcnew ObjectConsumer::Consumer();
obj->put_Name(_T("MyName"));
consumer->PassObject(obj);
CoUninitialize();
return 0;
}
這段代碼不會編譯。 編譯器無法將參數 1 從“IObjectToPassPtr”轉換為“Interop::ComTest::IObjectToPass ^”。 我進行了不同的嘗試,但似乎 IObjectToPass* 無法轉換為“Interop::ComTest::IObjectToPass^”。 有沒有辦法做到這一點?
跳過 COM 接口,只需在 C++ 中導出工廠函數。
#define MY_API __declspec(dllexport)
#ifdef __cplusplus
# define EXTERNC extern "C"
#else
# define EXTERNC
#endif
EXTERNC MY_API IObjectToPass* APIENTRY MyFactory(void);
EXTERNC MY_API void APIENTRY SomeFunction(IObjectToPass* handle);
// Implementation:
MY_API IObjectToPass* APIENTRY MyFactory(void)
{
return new ObjectToPass();
}
MY_API void APIENTRY SomeFunction(IObjectToPass* handle)
{
handle->DoFunction();
}
// And then export any needed functions too.
現在在 C# 中:
public class MyWrapper{
IntPtr myReference;
public ObjectWrapper()
{
try
{
this.myReference = MyFactory();
if (myReference == IntPtr.Zero)
{
throw "Error or something";
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
throw e;
}
}
//Path to dll
[DllImport(lib_path)]
private static extern IntPtr MyFactory();
[DllImport(lib_path)]
private static extern void SomeFunction(IntPtr toTrigger);
}
考慮擺脫 C 的三種形式中的至少一種以簡化設計,否則我建議的方法確實有效並且我以前使用過它!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.