我有一个较旧的应用程序,它接受dll插件。每个插件都有一个创建“小部件”的新实例的功能。此函数通过返回唯一的 int 来标识新的“窗口小部件”实例。在c ++插件模板中,我通过声明一个新的小部件 struct 并将其指针强制转换为 int 作为唯一标识符(不是我的想法,但我必须使用它):
struct widget {
...
};
int widget_instance (HWND hwnd) {
widget* myWidget = new widget;
...
return (int) myWidget;
}
我正在为这个应用程序开发一个c#插件,我需要在c#中复制这个机制。如何在函数内部声明一个struct,这样每次调用该函数时它都会返回一个固定的,不变的指向新声明的struct的指针?到目前为止我的代码:
public struct Widget {
...
}
public static int widget_instance(uint hwnd) {
Widget w = new Widget();
...
IntPtr myWidget = Marshal.AllocCoTaskMem(Marshal.SizeOf(w));
Marshal.StructureToPtr(w, myWidget, false);
return (int) myWidget;
}
这看起来是对的吗?我是否需要“固定”结构才能使其像c ++一样工作?
编辑:详细说明:唯一ID不仅仅是一个简单的“cookie” int ,它实际上在c ++模板中稍后用于访问 struct 实例通过将ID转换为指针:
widget* w = (widget*) WidgetID;
w->firstElement = 123;
我认为c#等价物是:
widget w = (widget)Marshal.PtrToStructure((IntPtr)widgetID,typeof(widget));
w.firstElement = 123;
答案 0 :(得分:1)
您似乎暗示返回的整数标识符只是一个cookie,并且应用程序不会将其视为指针。这意味着应用程序永远不会在窗口小部件上执行操作,但总是要求插件代表应用程序执行操作。如果是这种情况,则没有理由不使用自己的方案来分配cookie标识符。所以......
您可以在Widget类中添加“cookie”成员,并为分配Cookie添加静态“下一个cookie”成员。这将是一个简单且语义上合理的实现。显然,它需要线程安全措施。它还可以避免使用C ++技术将“this”指针转换为int,你说你不喜欢它,尽管我认为它非常好。
除了提供唯一标识符之外,C ++指针到int转换技术可能还有第二个目的。当应用程序为插件提供cookie时,插件可以通过将cookie转换回指针来直接找到窗口小部件并且运行时成本为零。虽然这不安全。但我不认为你能在C#中做到这一点。
您提出的C#代码意味着对于应用程序要求的每个小部件,您只需要创建并初始化第二个小部件。如果您真的想模仿C ++技术,以确保您的cookie在整个流程范围内是唯一的,而不是在单个插件中唯一,那么您可以只分配一个字节的块但不初始化它。或者甚至是一个零大小的块,但我不确定那会产生唯一的地址。
答案 1 :(得分:0)
是的,这是正确的,因为AllocCoTaskMem
从非托管 COM分配器分配内存。
仅分别使用FreeCoTaskMem
或ReAllocCoTaskMem
函数释放或重新定位内存。