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

问题描述 投票:0回答:1

我正在尝试从托管C ++ / CLI调用本机Windows API。其中一个论点是无效**。我们的想法是该函数将分配一个内存结构并返回一个指向调用者的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);
        }
    };
}
c++-cli marshalling
1个回答
0
投票

IntPtr可以转换为void*,但它不是同一类型。

由于参数是out-only,简单的解决方案就是使用临时的:

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)
© www.soinside.com 2019 - 2024. All rights reserved.