如何将 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代码,设置回调函数指针。并且您希望客户端代码直接写入分配大小为 buflen 的 buffer。某种错误指示会很有用,同时允许客户端代码指定它实际写入缓冲区的字节数。因此 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));
}
我正在做一个 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代码,设置回调函数指针。并且您希望客户端代码直接写入分配大小为 buflen 的 buffer。某种错误指示会很有用,同时允许客户端代码指定它实际写入缓冲区的字节数。因此 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));
}