通过 C# 在 LabVIEW 中处理事件 - 未找到类型 PROP.PropEngine 上的构造函数节点
Event handling in LabVIEW via C#- Constructor Node on type PROP.PropEngine not found
我正在 LabVIEW 中构建一个应用程序,它需要我通过回调注册 .NET 事件。我得到的 API 中没有 public 事件,所以我无法正确注册它们。此外,我尝试创建的构造函数无法正常工作。一般来说,我对事件处理和 C# 还很陌生,所以如果我的描述中有任何遗漏,我深表歉意。
使用与我合作的公司提供的 API,我制作了这个事件处理程序:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PROP.PropEngine;
namespace IMTEventHandler
{
public delegate void PropEngineEventHandlerDelegate(object sender, PROP.PropEngine.PropEngineEventArgs eventArgs);
public class IMTDelegate
{
public static event PROP.PropEngine.EventHandler PropEvent
{
add { inner.PropEvent += value; }
remove { inner.PropEvent -= value; }
}
public static void PropEngineEventHandlerFunc(object sender, PROP.PropEngine.PropEngineEventArgs eventArgs)
{
return ;
}
public PropEngineEventHandlerDelegate propEventHandler = PropEngineEventHandlerFunc;
//Pointer to our Event Handler
}
}
他们的文档说构造函数接受一个指向事件处理程序的函数指针,例如:
_propEngine = new PropEngine(propEventHandlerFunc)
虽然我无法访问原始代码,所以我认为我应该创建自己的 class,函数指针是 class 的 property/member :
public PropEngineEventHandlerDelegate propEventHandler = PropEngineEventHandlerFunc;
我认为我可以将它写成一个私有函数而不用 new class,但不幸的是,最终应用程序不允许这样做。
在应用程序中,当我试图将此函数指针传递给构造函数时遇到了一些 class 冲突,但我只是想我必须进行类型转换才能使它们工作(菜鸟错误)。现在我得到这个构造函数节点错误,我认为这是因为我发送的指针是一个错误的指针。
文档指出事件处理程序应采用两个参数:
void PropEngineEventHandlerFunc(object sender, PROP.PropEngine.PropEngineEventArgs eventArgs)
sender
是一个对象,eventArgs
是一个包含所有事件数据的 'struct' 类型。
问题:我的函数指针坏了,但我不知道为什么。此外,事件类型没有公开,所以我无法解释它们(我认为)。
您当前的方法有两个主要障碍:
- LabVIEW 无法创建委托,因此无法构造
PropEngine
,因为(根据您的说法)其构造函数需要 PropEngine.EventHandler
委托。
- 通过使用静态事件和事件处理程序,您的 LabVIEW 程序仅限于单个
PropEngine
实例。
您创建适配器的想法将使您能够使用 PropEngine
class,只需稍微重构一下即可。
C# 适配器
我在 Class 库 (.dll) 中写了两个 classes:
MockProp
-- 这是对您 API 的猜测
MockPropAdapter
-- 允许 LabVIEW 使用 MockProp
class
适配器公开了一个 public 事件,LabVIEW 可以使用 Register Event Callback
node 订阅该事件。只要您的 LabVIEW 程序创建适配器并在使用适配器创建 PropEngine 实例之前订阅其事件,就会在引发 PropEngine 事件时调用您的 LabVIEW 回调 VI。
using System;
namespace MockProp
{
// This is my sketch of the API you've been given.
public class MockProp
{
// I'm assuming that the API publishes the event handler's signature.
public delegate void MockPropEventHandler(object sender, EventArgs args);
// I'm assuming that the API's event is instance-based and not static.
private event MockPropEventHandler MockPropEvent;
// I'm assuming that it's keeping a reference to your event handler.
private MockPropEventHandler clientHandler;
public MockProp(MockPropEventHandler eventHandler)
{
this.clientHandler = eventHandler;
// I'm assuming that it also auto-subscribes to the event because it is a constructor parameter.
this.MockPropEvent += this.clientHandler;
}
// Provide an easy way for LabVIEW to trigger the event for demonstration purposes.
public void NotifyEvent()
{
if (this.MockPropEvent != null)
{
var args = new EventArgs();
this.MockPropEvent(sender: this, args: args);
}
}
// Allow the object to be garbage collected by removing all retaining references.
public void Release()
{
this.MockPropEvent -= this.clientHandler;
this.clientHandler = null;
}
}
// Here's one way to allow LabVIEW to subscribe to and handle private events
public class MockPropAdapter
{
private MockProp mockProp;
public MockPropAdapter()
{
// NOOP
}
// LabVIEW can subscribe to this event.
public event MockProp.MockPropEventHandler MockPropEventRepeater;
public MockProp CreateMockProp()
{
if (this.MockPropEventRepeater == null)
{
throw new InvalidOperationException(message:
"Subscribe to MockPropEventRepeater first. Otherwise, the Prop's event cannot be repeated.");
}
else
{
this.mockProp = new MockProp(eventHandler: this.MockPropEventRepeater);
return this.mockProp;
}
}
private void RepeatMockPropEvent(object sender, EventArgs args)
{
if (this.MockPropEventRepeater != null)
{
this.MockPropEventRepeater(sender, args);
}
}
}
}
LabVIEW 客户端
在下面的框图片段中,LabVIEW 程序:
- 创建适配器
- 注册转发器事件
- 使用适配器创建一个
MockProp
实例
- 使用
MockProp
实例引发事件
- 这是handler VI处理事件的时候
- 取消订阅转发器事件
- 释放
MockProp
个实例
- 释放适配器
我正在 LabVIEW 中构建一个应用程序,它需要我通过回调注册 .NET 事件。我得到的 API 中没有 public 事件,所以我无法正确注册它们。此外,我尝试创建的构造函数无法正常工作。一般来说,我对事件处理和 C# 还很陌生,所以如果我的描述中有任何遗漏,我深表歉意。
使用与我合作的公司提供的 API,我制作了这个事件处理程序:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PROP.PropEngine;
namespace IMTEventHandler
{
public delegate void PropEngineEventHandlerDelegate(object sender, PROP.PropEngine.PropEngineEventArgs eventArgs);
public class IMTDelegate
{
public static event PROP.PropEngine.EventHandler PropEvent
{
add { inner.PropEvent += value; }
remove { inner.PropEvent -= value; }
}
public static void PropEngineEventHandlerFunc(object sender, PROP.PropEngine.PropEngineEventArgs eventArgs)
{
return ;
}
public PropEngineEventHandlerDelegate propEventHandler = PropEngineEventHandlerFunc;
//Pointer to our Event Handler
}
}
他们的文档说构造函数接受一个指向事件处理程序的函数指针,例如:
_propEngine = new PropEngine(propEventHandlerFunc)
虽然我无法访问原始代码,所以我认为我应该创建自己的 class,函数指针是 class 的 property/member :
public PropEngineEventHandlerDelegate propEventHandler = PropEngineEventHandlerFunc;
我认为我可以将它写成一个私有函数而不用 new class,但不幸的是,最终应用程序不允许这样做。
在应用程序中,当我试图将此函数指针传递给构造函数时遇到了一些 class 冲突,但我只是想我必须进行类型转换才能使它们工作(菜鸟错误)。现在我得到这个构造函数节点错误,我认为这是因为我发送的指针是一个错误的指针。
文档指出事件处理程序应采用两个参数:
void PropEngineEventHandlerFunc(object sender, PROP.PropEngine.PropEngineEventArgs eventArgs)
sender
是一个对象,eventArgs
是一个包含所有事件数据的 'struct' 类型。
问题:我的函数指针坏了,但我不知道为什么。此外,事件类型没有公开,所以我无法解释它们(我认为)。
您当前的方法有两个主要障碍:
- LabVIEW 无法创建委托,因此无法构造
PropEngine
,因为(根据您的说法)其构造函数需要PropEngine.EventHandler
委托。 - 通过使用静态事件和事件处理程序,您的 LabVIEW 程序仅限于单个
PropEngine
实例。
您创建适配器的想法将使您能够使用 PropEngine
class,只需稍微重构一下即可。
C# 适配器
我在 Class 库 (.dll) 中写了两个 classes:
MockProp
-- 这是对您 API 的猜测
MockPropAdapter
-- 允许 LabVIEW 使用MockProp
class
适配器公开了一个 public 事件,LabVIEW 可以使用 Register Event Callback
node 订阅该事件。只要您的 LabVIEW 程序创建适配器并在使用适配器创建 PropEngine 实例之前订阅其事件,就会在引发 PropEngine 事件时调用您的 LabVIEW 回调 VI。
using System;
namespace MockProp
{
// This is my sketch of the API you've been given.
public class MockProp
{
// I'm assuming that the API publishes the event handler's signature.
public delegate void MockPropEventHandler(object sender, EventArgs args);
// I'm assuming that the API's event is instance-based and not static.
private event MockPropEventHandler MockPropEvent;
// I'm assuming that it's keeping a reference to your event handler.
private MockPropEventHandler clientHandler;
public MockProp(MockPropEventHandler eventHandler)
{
this.clientHandler = eventHandler;
// I'm assuming that it also auto-subscribes to the event because it is a constructor parameter.
this.MockPropEvent += this.clientHandler;
}
// Provide an easy way for LabVIEW to trigger the event for demonstration purposes.
public void NotifyEvent()
{
if (this.MockPropEvent != null)
{
var args = new EventArgs();
this.MockPropEvent(sender: this, args: args);
}
}
// Allow the object to be garbage collected by removing all retaining references.
public void Release()
{
this.MockPropEvent -= this.clientHandler;
this.clientHandler = null;
}
}
// Here's one way to allow LabVIEW to subscribe to and handle private events
public class MockPropAdapter
{
private MockProp mockProp;
public MockPropAdapter()
{
// NOOP
}
// LabVIEW can subscribe to this event.
public event MockProp.MockPropEventHandler MockPropEventRepeater;
public MockProp CreateMockProp()
{
if (this.MockPropEventRepeater == null)
{
throw new InvalidOperationException(message:
"Subscribe to MockPropEventRepeater first. Otherwise, the Prop's event cannot be repeated.");
}
else
{
this.mockProp = new MockProp(eventHandler: this.MockPropEventRepeater);
return this.mockProp;
}
}
private void RepeatMockPropEvent(object sender, EventArgs args)
{
if (this.MockPropEventRepeater != null)
{
this.MockPropEventRepeater(sender, args);
}
}
}
}
LabVIEW 客户端
在下面的框图片段中,LabVIEW 程序:
- 创建适配器
- 注册转发器事件
- 使用适配器创建一个
MockProp
实例 - 使用
MockProp
实例引发事件 - 这是handler VI处理事件的时候
- 取消订阅转发器事件
- 释放
MockProp
个实例 - 释放适配器