将 C# 委托传递给 C++/CLI 包装器

Passing a C# delegate to a C++/CLI wrapper

本文关键字:C++ CLI 包装      更新时间:2023-10-16

>我按照此示例使用 c# 委托作为 c++ 回调。

我的包装器看起来像这样:

// GLFWWrapper.h
#pragma once
using namespace System;
namespace GLFWWrapper {
    typedef void(__stdcall *KEY_CALLBACK)(int, int, int, int);
    public ref class Window {
        public:
            void setKeyCallback(KEY_CALLBACK fp);
            static KEY_CALLBACK csharpKeyCallback;
        ...
    };
}  
// GLFWWrapper.cpp
#include "stdafx.h"
#include "GLFWWrapper.h"
namespace GLFWWrapper {
    void cppKeyCallback(GLFWwindow * window, int key, int scancode, int action, int mods) {
        if (Window::csharpKeyCallback) {
            Window::csharpKeyCallback(key, scancode, action, mods);
        }
    }
    void Window::setKeyCallback(KEY_CALLBACK fp) {
        csharpKeyCallback = fp;
    }
    ...
}

cppKeyCallback函数是我在另一个函数(glfwSetKeyCallback(m_ptr, cppKeyCallback);)中设置的回调。csharpKeyCallback应该是我的 C# 项目的委托。在我上面链接到的示例中,仅解释了如何从包装器内部设置委托。但是如何从我的 C# 项目设置委托呢?当我尝试从我的 C# 项目调用setKeyCallback时,出现错误 Window.setKeyCallback(?) is not supported by the language

您似乎缺少指令的托管部分:

#pragma managed
public delegate void keyCallback(int, int, int, int);
void Window::setKeyCallback(keyCallback^ fp) {
    csharpKeyCallback = fp;
}

为了将对函数实例(委托)的引用从 C# 传递到 C++\CLI,您需要声明它,即声明一个托管委托。这可以在 C# 或 C++\CLI 中完成。

在代码中,KEY_CALLBACK是非托管函数声明。因此,它是"语言不支持的"。C# 端不能将其用作委托声明。

为了避免这种混乱,我自己总是让我的 C++\CLI 项目没有任何托管声明,并在从 C++\CLI 包装器和 C# 端引用的附加 C# 类库中提供这些声明。

编辑:不要忘记在托管方法声明中的托管引用类型之后放置^符号,否则编译器会破坏您并显示错误"此处不允许委托类型"。