我在 C++ 中有这段代码
class MyClass { ... };
typedef MyClass (*Callback)();
Callback theCB;
static void RegisterCallback( Callback cb ) { theCB = cb; };
static void CallCallback() {
MyClass obj = theCB();
}
我正在使用 swig 但为简单起见(如果你不知道 swig)我在 C# 中有这个包装器
public class MyClassWrapper
{
public IntPtr ptrToNativeObj; // pointer to native MyClass object
public MyClassWrapper()
{
ptrToNativeObj = call to native code that creates
and returns a new instance of MyClass in C++
}
};
现在我想支持 C# 中的回调机制,所以我这样设置:
public MyClassWrapper MyFunction()
{
return new MyClassWrapper();
}
delegate MyClassWrapper CallbackDotNet();
static void main()
{
var fct = new CallbackDotNet( MyFunction );
P/Invoke call to native function RegisterCallback( fct );
then finally:
P/Invoke call to native function CallCallback();
}
我有所有这些代码设置可以正常工作。CallCallback 中的本机代码将正确调用 MyFunction。
但现在我需要正确处理返回的对象......
MyFunction 返回一个 C# 引用,而 C++ 中的回调按值返回,因此这不会免费工作:
static void CallCallback() {
MyClass obj = theCB();
}
如何编组对从 MyFunction 返回的 MyClassWrapper 对象的“引用”,以便 C++ 接收“按值”一个 MyClass 对象?
我应该继续编写自定义编组器吗?
http://msdn.microsoft.com/en-us/library/zk0a8dea(v=vs.90).aspx
然后像这里一样使用它
[return: MarshalAs(UnmanagedType.CustomMarshaler,
MarshalType = "MyCustomMarshaler")]
delegate MyClassWrapper CallbackDotNet();
我查看了自定义编组器的文档,它非常复杂。看起来有趣的实现方法如下:
IntPtr MarshalManagedToNative( Object ManagedObj );
代码将类似于
IntPtr MarshalManagedToNative( Object ManagedObj )
{
MyClassWrapper val = ManagedObj as MyClassWrapper;
return val.ptrToNativeObj;
}
但这会将 MyClass* 返回到本机代码,而不是该 C++ 代码所期望的 MyClass 值!
static void CallCallback() {
MyClass obj = theCB();
}
编组器是否足够聪明以取消对指针的引用?