如何将 C++/CX 运行时对象转换为本机 C 指针类型?

How do I cast C++/CX runtime object to native C pointer type?

我正在做一个 C++/CX 运行时包装器,我需要将 C++/CX 对象指针传递给本机 C。我该怎么做,并将本机指针转换回 C++/CX对象引用类型?

void XClassA::do(XClass ^ B)
{
    void * ptr = (void*)(B);   // how to convert it?
}

而且,C++/CX 使用引用计数,如果我将对象引用转换为本地指针,我该如何管理指针生命周期?


更新(来自@Hans Passant 的请求)

问题背景,

母语 C

我正在尝试使用 C++/CX 包装 Native C 库(不是 C++)作为 Windows Runtime Component。 Native c有很多回调函数,声明如下,

例如,

//declare in native c
typedef int (GetData*)(void *, char* arg1, size_t arg2);

void * 是指向对象实例的指针。
并且回调将在运行时在本机 c 中执行。
我们期望 Application(C#/C++CX ...) 实现该方法。

WinRT 包装器 (C++/CX)

我的想法如下,

(1) 向应用程序

提供 interface
// XRtWrapperNamespace
public interface class XWinRtDataWrapper
{
    //declare in base class
    void getData(IVector<byte> ^ data);
}

让Application实现功能。由于我无法导出本机数据类型,因此我提供 IVector 从应用程序获取数据。

(2) 声明一个全局回调函数,将 IVector<byte>^ 转换为原生数据类型 char *,如下所示,

// when Native C executes callback function, 
// it will forward in the method in C++/CX. 
// The method calls the implementation method via object pointer.
// (And here is my my question)   
void XRtWrapperNamespace::callbackWrapper(void * ptr, char *, int length)
{ 
    // create Vector to save "out" data
    auto data = ref new Vector<byte>();
    // I expect I could call the implementation from Application.               
    ptr->getData(data);   // bad example. 

    // convert IVector data to char * 
    // ...
}

我的问题是

如何保持 windows 对本机 C 的对象引用? 看起来不可能,但有什么解决办法吗?

申请(示例)

 //Application
 public ref class XAppData: public XWinRtDataWrapper
 {
 public:
    virtual void getData(IVector<byte> ^ data) 
    {
      //implementation here
    }
 }

你的方向不对。我假设你在你的组件中#include a c header:

extern "C" {
#include "native.h"
}

而这个 header 包含:

typedef int (* GetData)(void* buffer, int buflen);
void initialize(GetData callback);

其中必须调用initialize()函数来初始化C代码,设置回调函数指针。并且您希望客户端代码直接写入分配大小为 buflenbuffer。某种错误指示会很有用,同时允许客户端代码指定它实际写入缓冲区的字节数。因此 int return 值。


WinRT 中函数指针的等价物是委托。因此,您需要声明一个在功能上与您的 C 函数指针相匹配的函数。在您的 .cpp 文件中写入:

using namespace Platform;

namespace YourNamespace {
    public delegate int GetDataDelegate(WriteOnlyArray<byte>^ buffer);
    // More here...
}

有两种基本方法可以让客户端代码使用委托。您可以添加一个让客户端设置委托的方法,等同于 initialize() 的工作方式。或者你可以引发一个事件,more WinRT-centric 方式。我会使用一个事件。请注意,实例化是一个问题,它们不是从多个组件 objects 到单个 C 函数指针的合适映射。我将通过声明事件 static 来掩盖这一点。编写 ref class 声明:

public ref class MyComponent sealed
{
public:
    MyComponent();
    static event GetDataDelegate^ GetData;
private:
    static int GetDataImpl(void* buffer, int buflen);
};

class构造函数需要初始化C代码:

MyComponent::MyComponent() {
    initialize(GetDataImpl);
}

并且我们需要使 C 回调引发事件的小适配器方法,以便客户端代码可以填充缓冲区:

int MyComponent::GetDataImpl(void* buffer, int buflen) {
    return GetData(ArrayReference<byte>((byte*)buffer, buflen));
}