c++/cli:委托给采用本机参数的托管方法
c++/cli: delegate to managed method taking native argument
我想找到一种方法来调用采用本机参数的引用 class 的方法。创建委托似乎是最明显的选择,但它不适用于此类方法。
请查看以下代码段
#pragma managed(push, off)
struct Native{};
#pragma managed(pop)
#pragma managed(push, on)
ref struct Managed{
// methods of managed class can take...
void method1(int){} // ...value types as an argument
void method2(System::String^){} // ...reference types as an argument
void method3(Native){} // ...native types as an argument, NICE!
};
int main(array<System::String ^>^ /*args*/) {
Managed^ m = gcnew Managed;
auto del1 = gcnew System::Action<int>(m, &Managed::method1); // ok
auto del2 = gcnew System::Action<System::String^>(m, &Managed::method2); // ok
auto del3 = gcnew System::Action<Native>(m, &Managed::method3); // error C3225: generic type argument for 'T' cannot be 'Native', it must be a value type or a handle to a reference type
}
#pragma managed(pop)
错误消息说:
error C3225: generic type argument for 'T' cannot be 'Native', it must be a value type or a handle to a reference type
这并不是说您不能从该方法中创建委托,只是您不能将其表示为 Action<Native>
。
您可以声明自己的委托类型,或使用可在泛型中使用的有效参数。
使用您自己的委托类型
public delegate void ActionOfNative(Native n);
auto del3 = gcnew ActionOfNative(m, &Managed::method3); // ok
使用可在泛型中使用的有效参数
这确实会改变您传递的参数的语义,但您可以改为传递一个指针。 IntPtr
类型实际上与 void*
相同。您可以将其用作参数类型。不过,您必须自己将 IntPtr
转换回 Native*
。
void method4(IntPtr ip){Native* np = (Native*)ip.ToPointer(); }
auto del4 = gcnew System::Action<IntPtr>(m, &Managed::method4); // ok
// Here's how you call del4.
Native n;
Native* np = &n;
IntPtr ip = IntPtr(np);
del4(IntPtr(&n));
del4(IntPtr(np));
del4(ip);
我想找到一种方法来调用采用本机参数的引用 class 的方法。创建委托似乎是最明显的选择,但它不适用于此类方法。
请查看以下代码段
#pragma managed(push, off)
struct Native{};
#pragma managed(pop)
#pragma managed(push, on)
ref struct Managed{
// methods of managed class can take...
void method1(int){} // ...value types as an argument
void method2(System::String^){} // ...reference types as an argument
void method3(Native){} // ...native types as an argument, NICE!
};
int main(array<System::String ^>^ /*args*/) {
Managed^ m = gcnew Managed;
auto del1 = gcnew System::Action<int>(m, &Managed::method1); // ok
auto del2 = gcnew System::Action<System::String^>(m, &Managed::method2); // ok
auto del3 = gcnew System::Action<Native>(m, &Managed::method3); // error C3225: generic type argument for 'T' cannot be 'Native', it must be a value type or a handle to a reference type
}
#pragma managed(pop)
错误消息说:
error C3225: generic type argument for 'T' cannot be 'Native', it must be a value type or a handle to a reference type
这并不是说您不能从该方法中创建委托,只是您不能将其表示为 Action<Native>
。
您可以声明自己的委托类型,或使用可在泛型中使用的有效参数。
使用您自己的委托类型
public delegate void ActionOfNative(Native n);
auto del3 = gcnew ActionOfNative(m, &Managed::method3); // ok
使用可在泛型中使用的有效参数
这确实会改变您传递的参数的语义,但您可以改为传递一个指针。 IntPtr
类型实际上与 void*
相同。您可以将其用作参数类型。不过,您必须自己将 IntPtr
转换回 Native*
。
void method4(IntPtr ip){Native* np = (Native*)ip.ToPointer(); }
auto del4 = gcnew System::Action<IntPtr>(m, &Managed::method4); // ok
// Here's how you call del4.
Native n;
Native* np = &n;
IntPtr ip = IntPtr(np);
del4(IntPtr(&n));
del4(IntPtr(np));
del4(ip);