如何通过 COM 接口调用 C# 方法传递函数指针
Posted
技术标签:
【中文标题】如何通过 COM 接口调用 C# 方法传递函数指针【英文标题】:How pass function pointer by call C# method via COM interfaces 【发布时间】:2012-01-04 14:11:26 【问题描述】:我有这个用于调用方法 WpfApplication1.NetLauncher.Launch(IntPtr cb) 的 CLI c++ 代码 通过反射:
#include "stdafx.h"
using namespace System;
using namespace System::Reflection;
typedef int (__stdcall *PMyBeep)();
int __stdcall MyBeep()
return 123;
[STAThreadAttribute]
int main(array<System::String ^> ^args)
Assembly^ asmbl = Assembly::Load("WpfDemo");
Type^ type = asmbl->GetType("WpfApplication1.NetLauncher");
Object^ obj = asmbl->CreateInstance("WpfApplication1.NetLauncher");
MethodInfo^ method = type->GetMethod("Launch");
IntPtr pp=(IntPtr)MyBeep;
Object^ magicValue = method->Invoke(obj, gcnew array<Object^>(1)pp);
return 0;
还有c#代码:
namespace WpfApplication1
public class NetLauncher
delegate int Mydelegate();
[System.STAThreadAttribute()]
public int Launch( IntPtr dwData)
//public int Launch(string path)
Mydelegate codeToRun = null;
codeToRun = (Mydelegate)Marshal.GetDelegateForFunctionPointer(dwData, typeof(Mydelegate));
int res = codeToRun.Invoke();
// ....
现在我尝试通过 COM 接口从 Win32 C++ 调用此方法:
// ....
CComPtr<IDispatch> disp = launcher.pdispVal;
DISPID dispid;
OLECHAR FAR* methodName = L"Launch";
hr = disp->GetIDsOfNames(IID_NULL, &methodName, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
// ????? DWORD nData=(DWORD)MyBeep;
// ????? CComVariant *func = new CComVariant(nData);
CComVariant FAR args[] = *func;
DISPPARAMS noArgs = args, NULL, 1, 0;
hr = disp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &noArgs, NULL, NULL, NULL);
我想我必须将函数指针(MyBeep)保存为 DISPPARAMS 中的 CComVariant,但我不知道怎么做???
【问题讨论】:
你不能只使用 void* 指针,因为你的托管代码无论如何都需要 IntPtr 吗? 你介意吗:CComVariant func = new CComVariant((void)MyBeep); ???它不起作用:( void* 和 IntPtr 都不是 COM 自动化兼容类型。通过不透明指针调用函数从根本上说是不安全且不可移植的。你可以抛开问题,但你不应该首先编写这样的代码。 【参考方案1】:我不在我的 Windows 机器前...你能帮我试试吗?
DISPPARAMS dispparams;
memset(&dispparams, 0, sizeof dispparams);
dispparams.cNamedArgs = 0;
dispparams.cArgs = 1;
dispparams.rgvarg = new VARIANTARG[dispparams.cArgs];
dispparams.rgvarg[0].vt = VT_I4;
dispparams.rgvarg[0].iVal = reinterpret_cast<int>(MyBeep);
【讨论】:
不幸的是它不起作用:Microsoft C++ 异常:内存位置 0x0019e678 处的 EEResourceException ..以上是关于如何通过 COM 接口调用 C# 方法传递函数指针的主要内容,如果未能解决你的问题,请参考以下文章
通过非默认 AppDomain 中的 C# 函数调用编组 C++ 指针接口
如何将委托或函数指针从 C# 传递到 C++ 并使用 InternalCall 调用它
从 C++ 传递函数指针以由 C# 调用 - 函数参数包括宽字符字符串 (LPCWSTR)