C#封装器和回调函数

5

我正在编写一个用于Dallmeier通用API Light(摄像头和监控系统)的C#封装器。我从未编写过封装器,但我曾使用过Canon EDSDK C#封装器。因此,我将Canon封装器作为编写Dallmeier封装器的指南。

目前,我遇到了将回调函数封装的问题。在API手册中,有以下内容:

dlm_connect

int(unsigned long uLWindowHandle,   
    const char * strIP,  
    const char* strUser1,  
    const char* strPwd1,  
    const char* strUser2,  
    const char* strPwd2,   
    void (*callback)(void *pParameters, void *pResult, void *pInput),   
    void * pInput)  

参数
- ulWindowhandle - 窗口的句柄,用于传递给ViewerSDK以在其中显示视频和消息
- strUser1/2 - 登录用户的名称。如果只使用单个用户登录,则strUser2为NULL
- strPwd1/2 - 两个用户的密码。如果strUser2为NULL,则忽略strPwd2。

返回值
此函数创建一个必须传递的SessionHandle。

回调
pParameters将被结构化:
- unsigned long ulFunctionID
- unsigned long ulSocketHandle, //已建立连接的套接字句柄
- unsigned long ulWindowHandle,
- int SessionHandle, //已创建会话的会话句柄
- const char * strIP,
- const char* strUser1,
- const char* strPwd1,
- const char* strUser2,
- const char * strPWD2
pResult是指向整数的指针,表示操作结果。成功时为零。负值为错误代码。

从我在网上和Stack Overflow上阅读的内容来看,C#使用委托来进行回调。因此,我创建了一个名为 my Callback 的函数:

public delegate uint DallmeierCallback(DallPparameters pParameters, IntPtr pResult, IntPtr pInput);

我创建了连接函数。
[DllImport("davidapidis.dll")]
public extern static int dlm_connect(int ulWindowHandle, string strIP, string strUser1, string strPwd1, string strUser2, string strPwd2, DallmeierCallback inDallmeierFunc

我认为DallPParameters是一个结构体:

[StructLayout(LayoutKind.Sequential)]
public struct DallPParameters
{
  public int ulfunctionID;
  public int ulsocketHandle;
  public int ulWindowHandle;
  ...
}

所有这些都在我的包装类中。
我是否朝着正确的方向前进,还是完全错误的?
然后在我的Dallmeier类中,我有以下内容:
    private DallmeierAPI dallmeierAPI;  
    private DallmeierSDK.DallmeierCallback dallCallbackHandler;  
    private GCHandle handle;  
    private IntPtr pResult;  
    private IntPtr pInput;  

    internal Dallmeier()
    {
        this.dallmeierAPI = DallmeierAPI.Instance;

        registerEvents();
    }

    private void registerEvents()
    {
        // Register Callback Events
        dallCallbackHandler = new DallmeierSDK.DallmeierCallback(pParameters, pResult, pInput); // Error: Method Name expected

        handle = GCHandle.Alloc(dallCallbackHandler);
    }

    private void unregisterEvents()
    {
        handle.Free();
    }

    private DallmeierSDK.DallPParameters pParameters(int ulfunctionID, int ulSocketHandl, int ulWindowHandle, int SessionHandle, string strIP, string strUser1, string strPwd1, string strUser2, string strPwd)
    {
        // what goes in here : Error not all code paths return a value
    }


}

当我注册回调函数时,它显示需要一个方法名?而且pParameters期望有一个返回值?

你的回调方法需要与委托类型的签名匹配。然后,你可以编写 new DallmeierSDK.DallmeierCallback(SomeMethodName) - SLaks
1个回答

3

你的方向基本正确。

然而,C中的long类型是32位的,应该映射到C#中的int类型。
此外,在调用函数后,您必须保留对传递的委托实例的托管引用,以确保该委托不会被垃圾回收。


1
我忘了将委托保留在某个地方...那真是太有趣了:)。+1提到参考文献。 - Tanzelax
感谢您的及时回复。我已经对帖子进行了编辑,并将longs更改为ints。我是否使用GCHandle.Alloc来保持托管引用? - fergs
或者在你的类中创建一个字段(假设这个类足够长久) - SLaks
我已经编辑了我的帖子,包括调用函数的细节,我在这方面遇到了一些问题。 - fergs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接