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

时间:2015-12-31 02:37:26

标签: windows-phone-8.1 c++-cx

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

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

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

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

问题的背景,

原生C

我正在尝试将C++/CX wrap 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来从Application获取数据。

(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
    }
 }

1 个答案:

答案 0 :(得分:2)

你没有走上正轨。我假设您在组件中#include一个c标头:

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

此标题包含:

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

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

WinRT中等效的函数指针是 delegates 。因此,您需要声明一个与C函数指针匹配的功能。在.cpp文件中写:

using namespace Platform;

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

让客户端代码使用委托有两种基本方法。您可以添加一个允许客户端设置委托的方法,相当于initialize()的工作方式。或者你可以举办一场以WinRT为中心的活动。我会用一个活动。请注意,实例化是一个问题,它们不具备从多个组件对象到单个C函数指针的良好映射。我将通过声明事件 static 来掩盖这一点。编写ref class声明:

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

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

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

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

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