如何将 void* 的引用从 C++/CLI 传递给本机 C 函数
Posted
技术标签:
【中文标题】如何将 void* 的引用从 C++/CLI 传递给本机 C 函数【英文标题】:How to pass a reference to a void* from C++/CLI to a native C function 【发布时间】:2019-04-03 00:07:31 【问题描述】:我正在尝试从托管 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);
;
【问题讨论】:
【参考方案1】: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)
【讨论】:
哇!感谢这一切。非常感谢您的帮助。以上是关于如何将 void* 的引用从 C++/CLI 传递给本机 C 函数的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 C++-CLI 回调和委托将字符串从 C++-CLI 传递到 C#