在非托管DLL中存储“托管”上下文参数

时间:2011-11-30 13:13:06

标签: c# .net dll interop

我不知道这是不是一个坏主意。我在C#中使用了一个非托管DLL(由我编写)。

可以在DLL中设置一些回调函数,但这些函数只能映射到C#端的静态类成员。

因为我想对特定的类实例进行回调操作,所以我想知道将类实例指针存储在DLL的状态信息中是否安全。

从DLL的角度来看,这只是一个32位的上下文整数,但是从C#方面来看,这将是一个实际的类“指针”或“引用”,回调签名定义如下:

public delegate void StatusChangeHandler(ContextClass context, int someCallbackValue);

它确实编译,它似乎确实有效,我只是不知道这是否有保证。这是可接受的做法吗?

1 个答案:

答案 0 :(得分:0)

我在这里看到的一个问题是.Net有一个垃圾收集器,可以移动你的类。因此,您保存的指针可能会失效。为了防止这种类型的简单类型,你应该像这样固定对象:

byte[] b = new byte[1000];
// pin b, and get pointer to the first element.
fixed (byte* ptr = &b)
{
   //use your fixed pointer to b. b will not be moved untill code leaves fixed region.
}

虽然对于复杂类型,.Net可能很聪明,可以自动固定对象,但我不会依赖它。 所以你写了这样的东西:

var ctx = new Context();
fixed (IntPtr ptr = &ctx)
{
    StatusChange(ptr);
    // do other stuff, and don't leave fixed region, until you can clear the pointer in the native library.
}

但实际上,我认为一种更简单可靠的方法是为您的上下文对象创建一个静态字典,并为您的本机dll提供该字典的一个键,可以是数字,字符串或GUID。例如。任何值,而不是指针。