如何将对void *的引用从C ++ / CLI传递到本机C函数

时间:2019-04-03 00:07:31

标签: c++-cli marshalling

我正在尝试从托管C ++ / CLI调用本地Windows API。参数之一是void **。想法是该函数将分配一个内存结构,并向调用方返回一个void指针,该指针应在下一次调用时传递回API。因此,我需要在托管端为指针分配存储空间,并将引用传递给C API。我不知道该怎么做。

我尝试在调用方中声明一个void *,并通过各种运算符传递引用:&,internal_ptr <>,pin_ptr <>。我对IntPtr也做了同样的事情。我收到错误消息,指出编译器无法将其转换为void **。

这是使用IntPtr和pin_ptr的一种尝试。我在第28行(声明pin_ptr的行)上得到以下编译错误:

E0144类型“ interior_ptr<System::IntPtr>”的值不能用于初始化类型“ cli::pin_ptr<void *>”的实体

#include <msclr\marshal.h>
using namespace msclr::interop;
using namespace System;

namespace CLRStorage
{
    public ref class CompoundFile
    {
    private:
        String ^ pathname;
        IntPtr pRootStorage;
    public:
        CompoundFile CompoundFile::Create(String^ path)
        {
            STGOPTIONS stgOptions;
            stgOptions.usVersion = 1;
            stgOptions.reserved = 0;
            stgOptions.ulSectorSize = 4096;
            stgOptions.pwcsTemplateFile = NULL;

            auto cf = gcnew CompoundFile();
            cf->pathname = path;
            marshal_context^ context = gcnew marshal_context();
            pin_ptr<void*> ppRootStorage = &cf->pRootStorage;
            StgCreateStorageEx(
                context->marshal_as<WCHAR*>(path),
                STGM_READWRITE & STGM_CREATE,
                STGFMT_DOCFILE,
                0,
                &stgOptions,
                NULL,
                IID_IStorage,
                ppRootStorage);
        }
    };
}

1 个答案:

答案 0 :(得分:0)

IntPtr可以与void*进行相互转换,但是类型不同。

由于该参数是唯一的,因此简单的解决方案是使用临时变量:

void* pRootStorage;
StgCreateStorageEx(
            context->marshal_as<WCHAR*>(path),
            STGM_READWRITE & STGM_CREATE,
            STGFMT_DOCFILE,
            0,
            &stgOptions,
            NULL,
            IID_IStorage,
            &pRootStorage);
cf->pRootStorage = IntPtr(pRootStorage);

这实际上也会快一点,因为不需要固定。

您还有一个错误的成员函数语法问题。你想要

static CompoundFile^ Create(String^ path)

代替

CompoundFile CompoundFile::Create(String^ path)

别忘了

return cf;

然后,marshal_context不是ref class,因此此行是错误的:

marshal_context^ context = gcnew marshal_context();

代替使用

marshal_context context;

由于它不是指针,

context.marshal_as<WCHAR*>(path)