如何通过 InvokeHelper 将 variant* 传递给 C#?
Posted
技术标签:
【中文标题】如何通过 InvokeHelper 将 variant* 传递给 C#?【英文标题】:How to pass variant* to C# through InvokeHelper? 【发布时间】:2018-10-17 04:21:33 【问题描述】:我有一个旧版 c++ 组件。它使用类似性质的 ATL 控件。程序 ID 输入到此组件。它使用 progid 创建 ATL 对象,并使用 dispatchid 使用 InvokeHelper 从 ATL 控件调用方法,如下所示,
DISPID methodDispID; // dispatchid
long lValue = 0; // first argument long
short nIdx = 1 // second argument short
VARIANT varValue; // third argument variant
long returnCode = 0; // return code long
static BYTE parms[] = VTS_I4 VTS_I2 VTS_PVARIANT;
InvokeHelper(methodDispID, DISPATCH_METHOD, VT_ERROR, (void*)&returnCode, parms, &varValue, lValue, nIdx);
在 C++ 中的 ActiveX 方法如下所示,
[id(1), helpstring("method GetValue")] long GetValue(long lValue, short nIdx,VARIANT *varValue);
现在我正在尝试在 C# 中引入 Active X,这意味着我有一个用户控件,我将这个 C# 用户控件的 progid 提供给遗留组件,它创建 C# 用户控件的对象并尝试调用 C# 用户控件的 GeValue 方法定义如下,
C#
interface IMyInterface
[DispId(1)] Int32 GetValue(System.Int32 lOrder, System.Int16
nIdx,object varval);
class MyClass : IMyInterface
System.Int32 GetValue(System.Int32 lValue, System.Int16 nIdx,
ref object vCBValue)
调用C#用户控件的GetValue方法,但抛出异常
System.Runtime.InteropServices.COMException 在 System.RuntimeType.ForwardCallToInvokeMember(System.String, System.Reflection.BindingFlags,System.Object,Int32[], System.Runtime.Remoting.Proxies.MessageData ByRef)
我尝试如下更改 C# 方法定义,但没有任何效果,
System.Int32 GetValue(System.Int32 lValue, System.Int16 nIdx,
[MarshalAs(UnmanagedType.Struct)] ref object varValue);
System.Int32 GetValue(System.Int32 lValue, System.Int16 nIdx,
ref IntPtr varValue);
注意:使用 InvokeHelper 调用方法的组件代码对于 C++ 和 C# 用户控件应该相同
【问题讨论】:
您的 GetValue 函数是否定义在接口中?请显示完整的代码。 @SimonMourier 我已经用接口定义更新了问题 您可以尝试在界面中为GetValue添加一个[PreserveSig]属性。 @SimonMourier 设置 [PreserveSig] 没有帮助:( 我们需要一个完整的复制代码才能提供帮助。 【参考方案1】:如果您尝试重现 c++ COM 代码:
[id(1), helpstring("method GetValue")]
long GetValue(long lValue, short nIdx,VARIANT *varValue);
...到 c#,然后代替
System.Int32 GetValue(System.Int32 lValue, System.Int16 nIdx, ref object vCBValue);
...应该是:
object GetValue(System.Int32 lValue, System.Int16 nIdx);
这是因为所有 c++ COM 方法都返回 HRESULT(在您的情况下为 long),任何其他返回值都是通过 out
参数。
在 .NET 中,无需定义 HRESULT,我们可以显式返回值,而不是使用 out
【讨论】:
在进行此更改后,也会引发相同的异常,而且我还有一个方法 [id(2), helpstring("method SetValue")] long SetValue(VARIANT* Var,VARIANT* bstrVal,long lOrder,short nIdx);如何在 C# 中制作它? @RajeshSubramanian 你也在 c# 中指定 progids 吗?通常你会在界面上这样做 @@MickyD 是的,我在接口方法中这样设置 DispID,[DispId(1)] Int32 GetValue(System.Int32 lOrder, System.Int16 nIdx,object varval); @RajeshSubramanian 我认为您可以将其放入一个新问题中。听起来好像您在将 c# 类导出到 COM 时遇到了更大的问题以上是关于如何通过 InvokeHelper 将 variant* 传递给 C#?的主要内容,如果未能解决你的问题,请参考以下文章
C++ 使用 C# DLL。 InvokeHelper 的问题
css Sticky Header che varia allo scroll
PHP HTML / CSS creando varios循环en varias columnas
HTML/CSS creando varios循环en varias columnas
xml Configurar Datasource con DBCP para utilizar Spring JDBC,namedParameters y varias cositas mas
sql MySQL:Conceder特权与una o varias tablas y campos。来自:https://www.sitepoint.com/community/t/mysql-per