我正在做一个C++/CX
运行时包装器,我需要将C++/CX
对象指针传递给本机C.我该怎么做,并将本机指针转换回C++/CX
对象引用类型?
void XClassA::do(XClass ^ B)
{
void * ptr = (void*)(B); // how to convert it?
}
而且,C++/CX
使用引用计数,如果我将Object引用转换为本机指针,我该如何管理指针生命周期?
问题的背景,
我正在尝试将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 ...)实现该方法。
我的想法如下,
(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
}
}
答案 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));
}